FragmentArgs (让你的Fragment的代码更少)讲解一

        对于搞android开发的人来讲,有些时候我们为了做一件很简单的事却要写大量的代码,这让人感到很不爽,比如在实现一个Fragment的时候.但庆幸的是java支持一个强大的工具:Annotation Processors

   在使用Fragment的时候,我们可能需要从外部传递一些数据给他,很多刚接触android开发的人可能会像下面这样实现它:

    

public class MyFragment extends Fragment {

  private int id;
  private String title;

  public static MyFragment newInstance(int id, String title) {
    MyFragment f = new MyFragment();
    f.id = id;
    f.title = title;
    return f;
  }

  @Override
    public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {

            Toast.makeText(getActivity(), "Hello " + title.substring(0, 3),
                Toast.LENGTH_SHORT).show();
      }
}


    像这样写它可以工作,但是当你尝试将你的手机从纵屏旋转到横屏并尝试访问id或title的时候你的应用程序会产生NullPointerException而导致程序crash掉。

    你可能会说我的应用程序是锁定在横屏或纵屏的,因此这个问题永远也不会发生。事情真的像你所想象的那样吗?

    但是你不要忘了,android是一个真正的多任务操作系统。在同一时间可能运行着多个应用程序。假如系统的内存不足时,android系统会销毁掉运行在后台的应用程序中的Activity(和包含的Fragment)。在平时的开发中,你可能并没有注意到这个问题,然而,一旦你的应用程序发布到应用商店之后,你会得到你的应用程序crash的通知。你可能会好奇为什么会产生crash。你的应用程序的用户在同一时间段里使用了多个应用程序,当你的应用程序是运行在后台的时候,他很有可能会被系统给销毁。例如,一个用户打开了你的应用程序,MyFragment是被显示在手机屏幕上,之后用户按下手机的Home键(你的应用程序进入后台),然后用户打开了另外的应用程序。这个时候如果手机的内存不足,系统为了释放掉内存,将销毁运行在后台的程序,也就是说你的应用程序在这时会被系统销毁。一段时间过后用户又回到了你的应用程序,例如按下多任务按钮,回到你的应用程序。现在android将会做些什么呢?android将恢复你的应用程序到之前的状态,恢复MyFragment到之前的状态。MyFragment尝试访问title,但是title将为空,因为它并没有被持久化保存。

     为了持久化的保存Fragment的数据,我们需要使用Fragment的setArguments(Bundle) and getArguments()

这两个方法。这样即使Fragment被销毁,他的数据也能恢复到之前的状态。但是这样做比较痛苦的是你使用setArguments方法写入数据之后必须调用getArguments方法获取数据,就像下边的代码这样:

public class MyFragment extends Fragment {

  private static String KEY_ID ="key.id";
  private static String KEY_TITLE = "key.title";

  private int id;
  private String title;

  public static MyFragment newInstance(int id, String title) {
    MyFragment f = new MyFragment();
    Bundle b = new Bundle();
    b.putInt(KEY_ID, id);
    b.putString(KEY_TITLE, title);
    f.setArguments(b);
    return f;
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
      // onCreate it's a good point to read the arguments
      Bundle b = getArguments();
      this.id = b.getInt(KEY_ID);
      this.title = b.getString(KEY_TITLE);
  }

  @Override
  public View onCreate(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {

            // No NullPointer here, because onCreate() is called before this
            Toast.makeText(getActivity(), "Hello " + title.substring(0, 3),
                Toast.LENGTH_SHORT).show();
      }
}

        你可能觉得这样做比较麻烦。那么有没有什么方法既能持久化的保存Fragment的数据状态,又不用写这么多代码呢。当然有,这就是我接下来要介绍给大家的一个开源库FragmentArgs。

    FragmentArgs开源库的地址:https://github.com/sockeqwe/fragmentargs

    FragmentArgs是一个轻量级的开源库,他用来为你的Frgament生成准确java代码,这个库使用简单。下边是使用FragmentArgs的示例代码:

    

import com.hannesdorfmann.fragmentargs.FragmentArgs;
import com.hannesdorfmann.fragmentargs.annotation.Arg;

public class MyFragment extends Fragment {

	@Arg
	int id;

	@Arg
	String title;

	@Override
	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		FragmentArgs.inject(this); // read @Arg fields
	}

	@Override
	public View onCreateView(LayoutInflater inflater,
		ViewGroup container, Bundle savedInstanceState) {

      		Toast.makeText(getActivity(), "Hello " + title,
      			Toast.LENGTH_SHORT).show();
      }
}

    大家会明显的发现使用FragmentArgs后我们少写了很多代码,这就是FrgamentArgs的强大之处。FragmentArgs会为你的Fragment中的注解属性生成样板代码。在你的Activity中你将使用FragmentArgs生成的Builder类代替new MyFragment(int id,String title)或静态的MyFragment.newInstance(int id,String title)方法。示例代码如下:

public class MyActivity extends Activity {

	public void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);

		int id = 123;
		String title = "test";

		// Using the generated Builder
		Fragment fragment =
			new MyFragmentBuilder(id, title)
			.build();

		// Fragment Transaction
		getFragmentManager()
			.beginTransaction()
			.replace(R.id.container, fragment)
			.commit();
	}

}

      你可能注意到Fragment的onCreate()方法里边的FragmentArgs.inject(this)语句。当调用该语句的时候FragmentArgs将会为你的Fragment生成相应的代码。你可能会问那我是不是必须要在我的每一个Fragment的onCreate方法里边都要调用这个方法呀?你并不需要在你的每一个Fragment的onCreate方法里边都调用这个语句,FragmentsArgs.inject(this)语句支持继承,你只需要写一个Fragment基类,在基类的onCreate方法里调用FragmentArgs.inject(this)语句,然后让其它的Fragment继承这个基类就行了。就像下边的代码这样

public class BaseFragment extends Fragment {

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        FragmentArgs.inject(this); // 读取 @Arg 属性
    }
}

public class MyFragment extends BaseFragment {

  @Arg
  String title;

  @Override
  public View onCreateView(LayoutInflater inflater,
    ViewGroup container, Bundle savedInstanceState) {

      Toast.makeText(getActivity(), "Hello " + title,
        Toast.LENGTH_SHORT).show();
  }

}

        关于FragmentArgs的用法就讲解完了,下一篇 FragmentArgs (让你的Fragment的代码更少)讲解二中 我将 讲解在使用FragemtArgs需要注意的一些问题。由于本人水平有限,如有错误和不足之处还请大家能够为我指出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
抱歉,我是AI语言模型,无法给出具体的代码,但是我可以提供一个示例: 一个activity中包含四个fragment,每个fragment对应不同的功能模块。例如: 1. 首页fragment:展示应用的主界面,包含一些常用功能按钮和推荐内容。 2. 消息fragment:展示用户的消息列表,包括系统通知、好友消息等。 3. 发现fragment:展示一些应用内的有趣内容,例如热门话题、推荐文章等。 4. 我的fragment:展示用户的个人信息及设置,包括账号管理、个人资料、隐私设置等。 在activity中通过使用FragmentTransaction进行添加、删除、替换等操作,可以实现四个fragment的动态切换。例如: ``` FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.add(R.id.container, new HomeFragment()); transaction.add(R.id.container, new MessageFragment()); transaction.add(R.id.container, new DiscoverFragment()); transaction.add(R.id.container, new ProfileFragment()); transaction.commit(); ``` 这样就可以将四个fragment添加到activity的container容器中。在需要切换fragment时,可以使用replace方法对当前fragment进行替换。例如: ``` FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); transaction.replace(R.id.container, new MessageFragment()); transaction.commit(); ``` 这样就可以将当前的fragment替换为消息fragment。通过这种方式,可以方便地实现activity中多个功能模块的切换和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值