fragment的使用注意问题

在上一篇主要讲解了fragment的一些基础用法,有兴趣的同学可以看看http://blog.csdn.net/qq_27970997/article/details/70036940那么这一篇主要讲解在使用fragment中的一些注意事项。


注意一:fragment回退栈的问题。

               如何实现回退栈,回退栈有什么作用呢?首先实现回退栈很简单,只需要在进行commit()之前添加addToBackStack(String)

,一般情况下String设置为null就可以。在上一篇我们讲到,当使用replace来进行fragment的切换的时候,前一个fragment的实例就会被销毁,那么如果我不想销毁实例的话有什么解决方法吗?当然有,你可以使用hide()和show()方法,他可以保证你的fragment的实例和视图不会被销毁。但是,如果我不想销毁实例但是我想重新加载视图的话怎么办呢?那就要用到我们的回退栈了。回退栈就是保留fragment的实例,但是会重新绘制fragment的视图。和detach()的作用是一样的。


注意二: Fragment与Activity通信

因为所有的Fragment都是依附于Activity的,所以通信起来并不复杂,大概归纳为:

a、如果你Activity中包含自己管理的Fragment的引用,可以通过引用直接访问所有的Fragment的public方法

b、如果Activity中未保存任何Fragment的引用,那么没关系,每个Fragment都有一个唯一的TAG或者ID,可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何Fragment实例,然后进行操作。当然,你需要提前为fragment设置TAG或者ID;

c、在Fragment中可以通过getActivity得到当前绑定的Activity的实例,然后进行操作。

注:如果在Fragment中需要Context,可以通过调用getActivity(),如果该Context需要在Activity被销毁后还存在,则使用getActivity().getApplicationContext()。


注意三:Fragment  Argument的使用

如何高效的实例化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间的解耦.


注意四:Fragment的startActivityForResult(MainActivity包含TestFragment,SecondActivity包含BlankFragment)

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        FragmentManager fm = getSupportFragmentManager();
        TestFragment mListFragment = (TestFragment) fm.findFragmentById(R.id.id_fragment_container);

        if(mListFragment == null ) {
            mListFragment = new TestFragment();
            fm.beginTransaction().add(R.id.id_fragment_container,mListFragment).commit();
        }
    }
首先在MainActivity里面加载TestFragment,需要注意的是必须对TestFragment进行非空验证,以确保唯一性。

public class TestFragment extends ListFragment {

    public static final int REQUEST_DETAIL = 0x110;
    private List<String> mTitles = Arrays.asList("hello","World","android");
    private int mCurrentPos;
    private ArrayAdapter<String> mAdapter;


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_test, container, false);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        setListAdapter(mAdapter = new ArrayAdapter<String>(getActivity(),android.R.layout.simple_list_item_1,mTitles));
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        super.onListItemClick(l, v, position, id);
        mCurrentPos  = position;
        Intent intent = new Intent(getActivity(), SecondActivity.class);
        intent.putExtra(BlankFragment.ARGUMENT, mTitles.get(position));
        startActivityForResult(intent,REQUEST_DETAIL);
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_DETAIL){
            mTitles.set(mCurrentPos, mTitles.get(mCurrentPos)+" -- "+data.getStringExtra(BlankFragment.RESPONSE));
            mAdapter.notifyDataSetChanged();
        }
    }
}
在TestFragment里面需要注意:在进行跳转的时候是跳转到目标所属的Activity,而不是直接跳转到对应的Fragment 。其他的写法和Activity的一样


public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        FragmentManager fm = getSupportFragmentManager();
        BlankFragment mContentFragment = (BlankFragment) fm.findFragmentById(R.id.id_fragment_container);

        if(mContentFragment == null ) {
            String title = getIntent().getStringExtra(BlankFragment.ARGUMENT);
            mContentFragment = BlankFragment.newInstance(title);
            fm.beginTransaction().add(R.id.id_fragment_container,mContentFragment).commit();
        }
    }
}
在SecondActivity里面加载BlankFragment,需要注意的是必须对BlankFragment进行非空验证,以确保唯一性。

public class BlankFragment 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(TestFragment.REQUEST_DETAIL, intent);
        }
    }


    public static BlankFragment newInstance(String argument) {
        Bundle bundle = new Bundle();
        bundle.putString(ARGUMENT, argument);
        BlankFragment contentFragment = new BlankFragment();
        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;
    }
}
注意onCreate()方法的写法


注意五:同一个Activity里面的fragment的数据传递(FragmentA弹出FragmentB(FragmentB为DialogFragment),FragmentB弹框消失时传递数据给FragmentA)


    @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)));
        tv.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {
                EvaluateDialog dialog = new EvaluateDialog();
                //注意setTargetFragment
                dialog.setTargetFragment(BlankFragment.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();
        }
    }
注意dialog.setTargetFragment(Fragment fragment,in t requestCode);这个方法,一般就是用于当前fragment由别的fragment启动,在完成操作后返回数据的


    // 设置返回数据
    protected void setResult(int which) {
        // 判断是否设置了targetFragment
        if (getTargetFragment() == null)
            return;

        Intent intent = new Intent();
        intent.putExtra(RESPONSE_EVALUATE, mEvaluteVals[which]);
        getTargetFragment().onActivityResult(BlankFragment.REQUEST_EVALUATE,
                Activity.RESULT_OK, intent);

    }


注意六:FragmentPagerAdapter和FragmentStatePagerAdapter

那么这两个类有何区别呢?

主要区别就在与对于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。

以上就是fragment使用过程中的一些注意事项,欢迎大家留言。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值