Android Fragment 你应当知道的全部-Android-优质IT资源分享社区

admin
管理员
管理员
  • UID1
  • 粉丝29
  • 关注4
  • 发帖数581
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:267回复:0

  Android Fragment 你应当知道的全部

楼主#
更多 发布于:2016-06-02 20:51

很久以前写过两篇Fragment的介绍,首要即是介绍其功用:Android Fragment
真实的完全解析(上)和Android Fragment 真实的完全解析(下)
有爱好的能够将就看下。之前的博客归于怎样运用Fragment,本文方针教你怎么用好Fragment,即Fragment的一些运用的主张,(多数内容来自:android
programming the big nerd ranch guide 一书,直接百度,你懂的,虽然是根底书本,仍是很值得一看的)。
1、概述
首要咱们简略回忆一下,信任咱们对Fragment的都不生疏,关于Fragment的运用,一方面Activity需求在规划中为Fragment组织方位,另一方面需求管理好Fragment的生命周期。Activity中有个FragmentManager,其内部保护fragment行列,以及fragment业务的回退栈。
通常状况下,咱们在Activity里面会这么增加Fragment:
public class MainActivity extends
FragmentActivity{     private ContentFragment mContentFragment  ;     @Override
    protected void onCreate(Bundle savedInstanceState)     {          
super.onCreate(savedInstanceState);          
setContentView(R.layout.activity_main);           FragmentManager fm =
getSupportFragmentManager();           mContentFragment = (ContentFragment)
fm.findFragmentById(R.id.id_fragment_container);           if(mContentFragment
== null )           {                 mContentFragment = new ContentFragment();
                
fm.beginTransaction().add(R.id.id_fragment_container,mContentFragment).commit();
          }     }}
关于上面代码,问两个疑问:
1、为何需求判null呢?
首要是由于,当Activity由于装备发生改动(屏幕旋转)或许内存不足被体系杀死,形成从头创立时,咱们的fragment会被保留下来,可是会创立新的FragmentManager,新的FragmentManager会首要会去获取保留下来的fragment行列,重建fragment行列,然后康复之前的状况。
2、add(R.id.id_fragment_container,mContentFragment)中的规划的id有何效果?
一方面呢,是奉告FragmentManager,此fragment的方位;另一方面是此fragment的仅有标识;就像咱们上面经过fm.findFragmentById(R.id.id_fragment_container)查找~~
好了,简略回忆了一下根本用法,详细的还请参阅上面的博客或许其他材料,接下来,介绍一些运用的定见~~
2、Fragment Arguments
下面描述一个简略的场景,比方咱们某个按钮触发Activity跳转,需求经过Intent传递参数到方针Activity的Fragment中,那么此Fragment怎么获取当时的Intent的值呢?
有哥们会说,这个简略?看我的代码(疑问代码):
public class ContentFragment extends Fragment{    
private String mArgument ;     public static final String ARGUMENT ="argument";
    @Override     public void onCreate(Bundle savedInstanceState)     {        
 super.onCreate(savedInstanceState);          mArgument =
getActivity().getIntent().getStringExtra(ARGUMENT);      }}
咱们直接在Fragment的onCreate中,拿到宿主Activty,宿主Activity中必定能经过getIntent拿到Intent,然后经过get办法,随意拿参数~~
这么写,功用上是实现了,可是呢?存在一个大疑问:咱们用Fragment的一个很大的因素,即是为了复用。你这么写,相当于这个Fragment现已完全和当时这个宿主Activity绑定了,复用直接废了~~~所以呢?咱们换种方式,引荐运用arguments来创立Fragment。
public class ContentFragment extends Fragment{    
 private String mArgument;      public static final String ARGUMENT =
"argument";      @Override      public void onCreate(Bundle savedInstanceState)
     {            super.onCreate(savedInstanceState);            // mArgument =
getActivity().getIntent().getStringExtra(ARGUMENT);            Bundle bundle =
getArguments();            if (bundle != null)                  mArgument =
bundle.getString(ARGUMENT);      }      /**        * 传入需求的参数,设置给arguments      
 * @param argument        * @return        */      public static ContentFragment
newInstance(String argument)      {            Bundle bundle = new Bundle();    
       bundle.putString(ARGUMENT, argument);            ContentFragment
contentFragment = new ContentFragment();          
 contentFragment.setArguments(bundle);            return contentFragment;    
 }}
给Fragment增加newInstance办法,将需求的参数传入,设置到bundle中,然后setArguments(bundle),最终在onCreate中进行获取;
这么就完结了Fragment和Activity间的解耦。当然了这儿需求留意:
setArguments办法必须在fragment创立今后,增加给Activity前完结。千万不要,首要调用了add,然后设置arguments。
3、Fragment的startActivityForResult
依旧是一个简略的场景:两个Fragment,一个展现文章列表的Fragment(叫做ListTitleFragment),一个显现详细信息的Fragment(叫做:ContentFragment),当然了,这两个Fragment都有其宿主Activity。
如今,咱们点击列表Fragment中的列表项,传入相应的参数,去详细信息的Fragment展现详细的信息,在详细信息页面,用户能够进行点评,当用户点击back今后,咱们以往点评成果显如今列表的Fragment关于的列表项中;
也即是说,咱们点击跳转到对应Activity的Fragment中,而且期望它能够回来参数,那么咱们必定是运用Fragment.startActivityForResult
;
在Fragment中存在startActivityForResult()以及onActivityResult()办法,可是呢,没有setResult()办法,用于设置回来的intent,这么咱们就需求经过调用getActivity().setResult(ListTitleFragment.REQUEST_DETAIL,
intent);。
详细代码:
ListTitleFragment
public class ListTitleFragment extends
ListFragment{      public static final int REQUEST_DETAIL = 0x110;      private
ListmTitles = Arrays.asList("Hello", "World", "Android");      private
int mCurrentPos ;      private ArrayAdaptermAdapter ;      @Override    
 public void onActivityCreated(Bundle savedInstanceState)      {          
 super.onActivityCreated(savedInstanceState);            setListAdapter(mAdapter
= new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1,
mTitles));      }      @Override      public void onListItemClick(ListView l,
View v, int position, long id)      {            mCurrentPos = position ;      
     Intent intent = new Intent(getActivity(),ContentActivity.class);          
 intent.putExtra(ContentFragment.ARGUMENT, mTitles.get(position));          
 startActivityForResult(intent, REQUEST_DETAIL);      }      @Override    
 public void onActivityResult(int requestCode, int resultCode, Intent data)    
 {            Log.e("TAG", "onActivityResult");          
 super.onActivityResult(requestCode, resultCode, data);          
 if(requestCode == REQUEST_DETAIL)            {                  
mTitles.set(mCurrentPos, mTitles.get(mCurrentPos)+" --
"+data.getStringExtra(ContentFragment.RESPONSE));                  
mAdapter.notifyDataSetChanged();            }    
 }}
ContentFragment
public class ContentFragment extends Fragment{    
private String mArgument;     public static final String ARGUMENT = "argument";
    public static final String RESPONSE = "response";     @Override     public
void onCreate(Bundle savedInstanceState)     {          
super.onCreate(savedInstanceState);           Bundle bundle = getArguments();  
        if (bundle != null)           {                 mArgument =
bundle.getString(ARGUMENT);                 Intent intent = new Intent();      
          intent.putExtra(RESPONSE, "good");                
getActivity().setResult(ListTitleFragment.REQUEST_DETAIL, intent);           }  
   }      public static ContentFragment newInstance(String argument)      {    
       Bundle bundle = new Bundle();            bundle.putString(ARGUMENT,
argument);            ContentFragment contentFragment = new ContentFragment();  
         contentFragment.setArguments(bundle);            return
contentFragment;      }      @Override      public View
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState)      {            Random random = new Random();          
 TextView tv = new TextView(getActivity());            tv.setText(mArgument);  
         tv.setGravity(Gravity.CENTER);          
 tv.setBackgroundColor(Color.argb(random.nextInt(100),          
 random.nextInt(255), random.nextInt(255), random.nextInt(255)));          
 return tv;      }}
贴出了两个Fragment的代码,能够看到咱们在ListTitleFragment.onListItemClick,运用startActivityForResult()跳转到方针Activity,在方针Activity的Fragment(ContentFragment)中获取参数,然后调用getActivity().setResult(ListTitleFragment.REQUEST_DETAIL,
intent);进行设置回来的数据;最终在ListTitleFragment.onActivityResult()拿到回来的数据进行回显;
为咱们今后在遇到相似疑问时,供给了解决方案;也说明晰一个疑问:fragment能够从Activity中接纳回来成果,可是其自设无法发生回来成果,只要Activity具有回来成果。
接下来我要贴一下,这两个Fragment的宿主Activity:
ListTitleActivity
public class ListTitleActivity extends
FragmentActivity{      private ListTitleFragment mListFragment;      @Override  
   protected void onCreate(Bundle savedInstanceState)      {          
 super.onCreate(savedInstanceState);          
 setContentView(R.layout.activity_single_fragment);            FragmentManager
fm = getSupportFragmentManager();            mListFragment = (ListTitleFragment)
fm.findFragmentById(R.id.id_fragment_container);            if(mListFragment ==
null )            {                   mListFragment = new ListTitleFragment();  
                
fm.beginTransaction().add(R.id.id_fragment_container,mListFragment).commit();  
         }      }}
ContentActivity:
public class ContentActivity extends
FragmentActivity{      private ContentFragment mContentFragment;      @Override
     protected void onCreate(Bundle savedInstanceState)      {            
super.onCreate(savedInstanceState);            
setContentView(R.layout.activity_single_fragment);             FragmentManager
fm = getSupportFragmentManager();             mContentFragment =
(ContentFragment) fm.findFragmentById(R.id.id_fragment_container);            
if(mContentFragment == null )             {                    String title =
getIntent().getStringExtra(ContentFragment.ARGUMENT);                  
 mContentFragment = ContentFragment.newInstance(title);                  
 fm.beginTransaction().add(R.id.id_fragment_container,mContentFragment).commit();
             }      }}
有没有发现两个Activity中的代码极其的相似,且运用了同一个规划文件:
activity_single_fragment.xml

为何要贴这Acticity的代码呢?由于咱们项目中,假如原则上运用Fragment,会发现大量相似的代码,那么咱们就能够笼统一个Activity出来,保管咱们的Single
Fragment。
详细见下一节。
4、SingleFragmentActivity
所以笼统出来的Activity的代码为:
package com.example.demo_zhy_23_fragments;import
android.os.Bundle;import android.support.v4.app.Fragment;import
android.support.v4.app.FragmentActivity;import
android.support.v4.app.FragmentManager;public abstract class
SingleFragmentActivity extends FragmentActivity{      protected abstract
Fragment createFragment();      @Override      protected void onCreate(Bundle
savedInstanceState)      {            super.onCreate(savedInstanceState);      
     setContentView(R.layout.activity_single_fragment);          
 FragmentManager fm = getSupportFragmentManager();            Fragment fragment
=fm.findFragmentById(R.id.id_fragment_container);            if(fragment == null
)            {                  fragment = createFragment() ;                
 fm.beginTransaction().add(R.id.id_fragment_container,fragment).commit();      
     }      }}
那么,有了这个SingleFragmentActivity,咱们的ContentActivity和ListTitleActivity也能大变身了~
package com.example.demo_zhy_23_fragments;import
android.support.v4.app.Fragment;public class ContentActivity extends
SingleFragmentActivity{      private ContentFragment mContentFragment;    
 @Override      protected Fragment createFragment()      {             String
title = getIntent().getStringExtra(ContentFragment.ARGUMENT);            
mContentFragment = ContentFragment.newInstance(title);             return
mContentFragment;      }}
package com.example.demo_zhy_23_fragments;import
android.support.v4.app.Fragment;public class ListTitleActivity extends
SingleFragmentActivity{      private ListTitleFragment mListFragment;    
 @Override      protected Fragment createFragment()      {            
mListFragment = new ListTitleFragment();             return mListFragment;    
 }}
是不是简练很多,信任优先运用Fragment的项目,相似的Activity十分多,运用SingleFragmentActivity来简化你的代码吧~~
好了,此代码是来自文章开端引荐的书中的,再次引荐一下~~。
5、FragmentPagerAdapter与FragmentStatePagerAdapter
信任这两个PagerAdapter的子类,咱们都不生疏吧~~自从Fragment面世,运用ViewPager再联系上面任何一个实例的制造APP主页的事例格外多~~~
那么这两个类有何差异呢?
首要差异就在与关于fragment是不是毁掉,下面细说:
FragmentPagerAdapter:关于不再需求的fragment,挑选调用detach办法,仅毁掉视图,并不会毁掉fragment实例。
FragmentStatePagerAdapter:会毁掉不再需求的fragment,当当时业务提交今后,会完全的将fragmeng从当时Activity的FragmentManager中移除,state标明,毁掉时,会将其onSaveInstanceState(Bundle
outState)中的bundle信息保留下来,当用户切换回来,能够经过该bundle康复生成新的fragment,也即是说,你能够在onSaveInstanceState(Bundle
outState)办法中保留一些数据,在onCreate中进行康复创立。
如上所说,运用FragmentStatePagerAdapter当然更省内存,可是毁掉新建也是需求时间的。通常状况下,假如你是制造主页面,就3、4个Tab,那么能够挑选运用FragmentPagerAdapter,假如你是用于ViewPager展现数量格外多的条目时,那么主张运用FragmentStatePagerAdapter。
篇幅因素,详细的事例就不写了,咱们自行测试。
6、Fragment间的数据传递
上面3中,咱们展现了,通常的两个Fragment间的数据传递。
那么还有一种对比特别的状况,即是两个Fragment在同一个Activity中:例如,点击当时Fragment中按钮,弹出一个对话框(DialogFragment),在对话框中的操作需求回来给触发的Fragment中,那么怎么数据传递呢?关于对话框的运用引荐:Android
官方引荐 : DialogFragment 创立对话框
咱们持续修正咱们的代码:如今是ListTitleFragment , ContentFragment
, 增加一个对话框:EvaluateDialog,用户点击ContentFragment 内容时弹出一个评估列表,用户挑选评估。
如今咱们的关注点在于:ContentFragment中怎么高雅的拿到EvaluateDialog中回来的评估:
记住咱们在一个Activity中,那么必定不是运用startActivityForResult;可是咱们回来的数据,仍然在onActivityResult中进行接纳。
好了看代码:
ContentFragment
public class ContentFragment extends Fragment{    
private String mArgument;     public static final String ARGUMENT = "argument";
    public static final String RESPONSE = "response";     public static final
String EVALUATE_DIALOG = "evaluate_dialog";     public static final int
REQUEST_EVALUATE = 0X110;     //...     @Override     public View
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState)     {           Random random = new Random();          
TextView tv = new TextView(getActivity());           ViewGroup.LayoutParams
params = new ViewGroup.LayoutParams(           LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);           tv.setLayoutParams(params);          
tv.setText(mArgument);           tv.setGravity(Gravity.CENTER);          
tv.setBackgroundColor(Color.argb(random.nextInt(100),          
random.nextInt(255), random.nextInt(255), random.nextInt(255)));           //
set click           tv.setOnClickListener(new OnClickListener()                
  {                          @Override                          public void
onClick(View v)                          {                              
 EvaluateDialog dialog = new EvaluateDialog();                              
 //留意setTargetFragment                              
 dialog.setTargetFragment(ContentFragment.this, REQUEST_EVALUATE);              
                 dialog.show(getFragmentManager(), EVALUATE_DIALOG);            
             }                   });           return tv;     }     //接纳回来回来的数据
    @Override     public void onActivityResult(int requestCode, int resultCode,
Intent data)     {          super.onActivityResult(requestCode, resultCode,
data);          if (requestCode == REQUEST_EVALUATE)          {              
 String evaluate = data.getStringExtra(EvaluateDialog.RESPONSE_EVALUATE);      
         Toast.makeText(getActivity(), evaluate, Toast.LENGTH_SHORT).show();    
           Intent intent = new Intent();              
 intent.putExtra(RESPONSE, evaluate);              
 getActivity().setResult(Activity.REQUEST_OK, intent);           }      }}
删除了一些无关代码,留意看,咱们在onCreateView中为textview增加了click事情,用于弹出咱们的dialog,留意一行代码:
dialog.setTargetFragment(ContentFragment.this,
REQUEST_EVALUATE);
咱们调用了Fragment.setTargetFragment
,这个办法,通常即是用于当时fragment由别的fragment发动,在完结操作后回来数据的,契合咱们的需求吧~~~留意,这句很主要。
接下来看EvaluateDialog代码:
package com.example.demo_zhy_23_fragments;import
android.app.Activity;import android.app.AlertDialog;import
android.app.Dialog;import android.content.DialogInterface;import
android.content.DialogInterface.OnClickListener;import
android.content.Intent;import android.os.Bundle;import
android.support.v4.app.DialogFragment;public class EvaluateDialog extends
DialogFragment{     private String[] mEvaluteVals = new String[] { "GOOD",
"BAD", "NORMAL" };     public static final String RESPONSE_EVALUATE =
"response_evaluate";     @Override     public Dialog onCreateDialog(Bundle
savedInstanceState)     {           AlertDialog.Builder builder = new
AlertDialog.Builder(getActivity());           builder.setTitle("Evaluate
:").setItems(mEvaluteVals, new OnClickListener()                                
{                                        @Override                              
         public void onClick(DialogInterface dialog, int which)                
                       {                                            
 setResult(which);                                        }                    
             });            return builder.create();      }      // 设置回来数据    
 protected void setResult(int which)      {             //
判别是不是设置了targetFragment             if (getTargetFragment() == null)            
       return;             Intent intent = new Intent();            
intent.putExtra(RESPONSE_EVALUATE, mEvaluteVals[which]);            
getTargetFragment().onActivityResult(ContentFragment.REQUEST_EVALUATE,
Activity.RESULT_OK, intent       );    }}
要点即是看点击后的setResult了,咱们首要判别是不是设置了targetFragment,假如设置了,意味咱们要回来一些数据到targetFragment。
咱们创立intent封装好需求传递数据,最终手动调用onActivityResult进行回来数据~~
最终咱们在ContentFragment的onActivityResult接纳即可。
ok,终于把这些tips贯穿到一起了,到此咱们的Fragment的一些主张的用法就结束了~~~那么,最终供给下源码,也趁便贴个效果图:

源码点击下载
转发请标明出处:http://blog.csdn.net/lmj623565791/article/details/42628537
转发请注明:Android开发中文站 » Android Fragment 你应当知道的全部




优质IT资源分享社区为你提供此文。
站有大量优质android教程视频,资料等资源,包含android基础教程,高级进阶教程等等,教程视频资源涵盖传智播客,极客学院,达内,北大青鸟,猎豹网校等等IT职业培训机构的培训教学视频,价值巨大。欢迎点击下方链接查看。
android教程视频
优质IT资源分享社区(www.itziyuan.top)
一个免费,自由,开放,共享,平等,互助的优质IT资源分享网站。
专注免费分享各大IT培训机构最新培训教学视频,为你的IT学习助力!

!!!回帖受限制请看点击这里!!!
!!!资源失效请在此版块发帖说明!!!

[PS:按 CTRL+D收藏本站网址~]

——“优质IT资源分享社区”管理员专用签名~

本版相似帖子

游客