Android开发经验谈Android

关于Fragment,你可能不知道的一切

2018-11-15  本文已影响286人  史蒂芬诺夫斯基

省略Fragment的生命周期

省略Fragment的静态加载

1.动态添加Fragment的方法
2.两个Fragment与Activity之间的通信(官方建议)

前提:

实现:

3.当Activity重启时,使用Fragment保存数据

当Activity的配置发生变化导致重启时,为了提高用户体验,一般需要在Activity销毁的时候保存界面上的一些数据,再次创建的时候恢复数据。

通常的做法是在 onSaveInstanceState()回调时保存有关应用状态数据,然后,可以在 onCreate()onRestoreInstanceState() 期间恢复 Activity 状态。

通过系统回调onSaveInstanceState()方法将数据保存在Boundle,但当数据量较大时,可能无法完全恢复 Activity 状态,因为它并非设计用于携带大型对象(例如位图Bitmap),而且其中的数据必须先序列化,再进行反序列化,这可能会消耗大量内存并使得配置变更速度缓慢。

在这种情况下,如果 Activity 因配置变更而重启,则可通过保留Fragment 来减轻重新初始化 Activity 的负担。

步骤如下:

例如:

定义一个RetainedFragment用来保存数据

public class RetainedFragment extends Fragment {

    // data object we want to retain
    private MyDataObject data;

    // this method is only called once for this fragment
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // retain this fragment
        setRetainInstance(true);
    }

    public void setData(MyDataObject data) {
        this.data = data;
    }

    public MyDataObject getData() {
        return data;
    }
}

注意:尽管可以存储任何对象,但是切勿传递与 Activity 绑定的对象,例如,DrawableAdapterView 或其他任何与 Context 关联的对象。否则,它将泄漏原始 Activity 实例的所有视图和资源。 (泄漏资源意味着应用将继续持有这些资源,但是无法对其进行垃圾回收,因此可能会丢失大量内存。)

然后,使用 FragmentManager 将片段添加到 Activity。在运行时配置变更期间再次启动 Activity 时,就可以获得片段中的数据对象。

public class MyActivity extends Activity {

    private RetainedFragment dataFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // find the retained fragment on activity restarts
        FragmentManager fm = getFragmentManager();
        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

        // create the fragment and data the first time
        if (dataFragment == null) {
            // add the fragment
            dataFragment = new DataFragment();
            fm.beginTransaction().add(dataFragment, “data”).commit();
            // load the data from the web
            dataFragment.setData(loadMyData());
        }

        // the data is available in dataFragment.getData()
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // store the data in the fragment
        dataFragment.setData(collectMyLoadedData());
    }
}
4.向应用栏添加项目

Fragment可以通过实现 onCreateOptionsMenu() 向 Activity 的选项菜单(并因此向应用栏)贡献菜单项。不过,为了使此方法能够收到调用,必须在 onCreate() 期间调用 setHasOptionsMenu(),以指示Fragment想要向选项菜单添加菜单项(否则,片段将不会收到对 onCreateOptionsMenu() 的调用)。

从Fragment添加到选项菜单的任何菜单项都将追加到现有菜单项之后。 选定菜单项时,Fragment还会收到对 onOptionsItemSelected() 的回调。

Fragment向应用栏添加项目应用十分广泛,例如下面的效果

我们自己也可以动手实现这样的效果,先看效果:

当切换Fragment的时候,应用栏不同的状态,so easy!

另外,还可以通过调用 registerForContextMenu(),在片段布局中注册一个视图来提供上下文菜单。用户打开上下文菜单时,片段会收到对 onCreateContextMenu() 的调用。当用户选择某个菜单项时,片段会收到对 onContextItemSelected() 的调用。

:尽管Fragment会收到与其添加的每个菜单项对应的菜单项选定回调,但当用户选择菜单项时,Activity 会首先收到相应的回调。 如果 Activity 对菜单项选定回调的实现不会处理选定的菜单项,则系统会将事件传递到片段的回调。 这适用于选项菜单和上下文菜单。

上一篇下一篇

猜你喜欢

热点阅读