zoukankan      html  css  js  c++  java
  • 关闭 Android Loaders(二)Loader的使用

    http://blog.csdn.net/liaoqianchuan00/article/details/24094733

    使用LoaderManager
    
    1.       简单的API让你的Activity/Fragment可以和Loaders进行交互。
    
    2.       每个Activity和每个Fragment只有一个LoaderManager的实例,他们不共享这些Loaders。
    
    3.       主要的方法:
    
     
    
    initLoader(intid, Bundle args, LoaderCallbacks<D> callbacks)
    
     
    
    restartLoader(intid, Bundle args, LoaderCallbacks<D> callbacks)
    
     
    
    destroyLoader(intid)
    
     
    
    getLoader(intid)
    
     
    
    privatefinal LoaderCallbacks<Result> loaderCallbacks
            = newLoaderCallbacks<Result>() {
    
          @Override
          public Loader<Result>onCreateLoader(int id, Bundle args) {
                 return newMyLoader(getActivity(), args.getLong("id"));
          }
    
          @Override
          public voidonLoadFinished(Loader<Result> loader, Result result) {
                 handleResult(result);
          }
    
          @Override
          public voidonLoaderReset(Loader<Result> loader) {
          }};
    
     
    
    注意:绝对不要直接调用一个Loader的框架方法,而你需要使用LoaderManager来自动调用。
    
     
    如何初始化Loaders
    
    在Activity中
    
     
    
           @Override
    
           protectedvoid onCreate(Bundle savedInstanceState) {
    
                  super.onCreate(savedInstanceState);
    
                  ...
    
                  getSupportLoaderManager().initLoader(LOADER_ID,null, callbacks);
    
           }
    
     
    
    在Fragment中
    
     
    
    @Override
    
           publicvoid onActivityCreated(Bundle savedInstanceState) {
    
                  super.onActivityCreated(savedInstanceState);
    
                  ...
    
                  getLoaderManager().initLoader(LOADER_ID,null, callbacks);
    
           }
    Loader状态
    
    每个Loader有三个状态:started,stopped,reset。而我们的LoaderManager会自动的根据Activity或者Fragment的状态来改变这些Loader的状态。
    
     
    
    1.       在Activity/FragmentstartsàLoader starts: onStartLoading()
    
    2.       Activity变成InVisible或者Fragment被detachedàLoader stops: onStopLoading()
    
    3.       Activity/Fragment被重新创建à没有回调。LoaderManager将会继续接收results,然后将结果保存到缓存。
    
    4.       Activity/Fragment被销毁或者restartLoader/destroyLoader被调用àLoader resets: onReset()
    
     
    使用Bundle
    
    private void onNewQuery(String query) {
    
                  Bundleargs = new Bundle();
    
                  args.putString("query",query);
    
                  getLoaderManager().restartLoader(LOADER_ID,args, loaderCallbacks);
    
           }
    
     
    
    ///////////////////////////////////
    
    @Override
    
           publicLoader<Result> onCreateLoader(int id, Bundle args) {
    
                  returnnew QueryLoader(getActivity(), args.getString("query"));
    
           }
    
     
    
    很多时候你都不需要使用参数,直接传入null。
    
    LoaderCallBacks是你的Fragment/Activity的一部分。你也可以直接使用Fragment/Activity的实例变量。
    
     
    
    @Override
    
           publicvoid onCreate(Bundle savedInstanceState) {
    
                  super.onCreate(savedInstanceState);
    
                  this.newsId= getArguments().getLong("newsId");
    
           }
    
    ...
    
           @Override
    
           publicLoader<News> onCreateLoader(int id, Bundle args) {
    
                  returnnew NewsLoader(getActivity(), NewsFragment.this.newsId);
    
           }
    
     
    LoaderManager的一个Bug
    
    当一个Fragment因为configuration变化被重新创建的时候(比如旋转屏幕,改变语言等),你在onActivityCreated()里面调用了initLoader()之后,他的LoaderManager调用了两次onLoadFinished。
    
     
    
    解决方案:
    
    1.       如果代码逻辑允许,可以不用处理。
    
    2.       将之前的result保存起来,检查结果是否有变化。
    
    3.       在onCreate()里面调用setRetainInstance(true)。
    
     
    One-shot Loader
    
    很多时候,我们只想运行一次这个Loader一次。比如:我们点击一个按钮然后提交一些信息到服务器。在用户点击了一个按钮后,我们调用initLoader,这个时候用户旋转屏幕,在旋转完屏幕之后,我们想要使用之前loader得到的结果。注意在旋转屏幕的时候,我们的Loader还没有提交完数据。像我们之前用AsyncTask的话,是没有办法在Activity/Fragment重新创建之后拿到之前任务返回的result的。但是使用Loader就简单多了。
    
     
    
    在LoaderCallbacks中加入下面的代码
    
     
    
    @Override
    
           publicvoid onLoadFinished(Loader<Integer> loader, Result result) {
    
                  getLoaderManager().destroyLoader(LOADER_ID);
    
                  ...            // Process the result
    
           }
    
     
    
    在Activity/Fragment的创建过程中加入:
    
     
    
    @Override
    
           publicvoid onActivityCreated(Bundle savedInstanceState) {
    
                  super.onCreate(savedInstanceState);
    
                  ...
    
                  //Reconnect to the loader only if present
    
                  if(getLoaderManager().getLoader(LOADER_ID) != null) {
    
                         getLoaderManager().initLoader(LOADER_ID,null, this);
    
                  }
    
           }
    
     
    常见的错误使用
    
    1.       滥用loader id。在创建和restart一个loader的时候,不需要每次都去增加这个ID值。对于某种Loader,只需要一个唯一的id值。
    
     
    
    2.       不需要在整个应用程序的范围类为每种Loader创建一个唯一的id值。因为每个LoaderManager都是独立的。你只需要保证你的Activity活着Fragment范围内这种Loader的ID值唯一就可以了。所以直接在Activity或者Fragment中创建一个私有的常量ID就可以了。
    
     
    
    3.       避免出现FragmentManager exceptions
    
     
    
    你不能在LoaderCallback这些回调里面直接创建FragmentTransaction(包括DialogFragment这种dialog)。
    
    解决方法就是使用Handler来处理FragmentTransaction。
    
    publicclass LinesFragment extends ContextMenuSherlockListFragment implementsLoaderCallbacks<List<LineInfo>>, Callback {
    
          ...
    
          @Override
    
          public void onCreate(BundlesavedInstanceState) {
    
                 super.onCreate(savedInstanceState);
    
                 handler = new Handler(this);
    
                 adapter = newLinesAdapter(getActivity());
    
          }
    
          @Override
    
          public void onActivityCreated(BundlesavedInstanceState) {
    
                 super.onActivityCreated(savedInstanceState);
    
                 setListAdapter(adapter);
    
                 setListShown(false);
    
                 getLoaderManager().initLoader(LINES_LOADER_ID,null, this);
    
          }
    
       @Override
    
          public Loader<List<LineInfo>>onCreateLoader(int id, Bundle args) {
    
                 return newLinesLoader(getActivity());
    
          }
    
          @Override
    
          public voidonLoadFinished(Loader<List<LineInfo>> loader, List<LineInfo>data) {
    
                 if (data != null) {
    
                        adapter.setLinesList(data);
    
                 } else if (isResumed()) {
    
                        handler.sendEmptyMessage(LINES_LOADING_ERROR_WHAT);
    
                 }
    
                 // The list should now be shown.
    
                 if (isResumed()) {
    
                        setListShown(true);
    
                 } else {
    
                        setListShownNoAnimation(true);
    
                 }
    
          }
    
    @Override
    
          public voidonLoaderReset(Loader<List<LineInfo>> loader) {
    
                 adapter.setLinesList(null);
    
          }
    
          @Override
    
          public boolean handleMessage(Messagemessage) {
    
                 switch (message.what) {
    
                 case LINES_LOADING_ERROR_WHAT:
    
                        MessageDialogFragment
                     .newInstance(R.string.error_title, R.string.lines_loading_error)
    
                      .show(getFragmentManager());
    
                        return true;
    
                 }
    
                 return false;
    
          }
  • 相关阅读:
    路由器01---k2刷Pandora
    nginx+flask02---概念
    Nginx06---实现websocket
    Nginx05---负载均衡 upsteam
    nginx+uwsgi02---django部署(推荐)
    Nginx04---实现直播
    Nginx04---编译安装
    mybatis+mysql insert添加数据后返回数据主键id---(转)
    JSON字符串转换为Map
    Http post请求案例
  • 原文地址:https://www.cnblogs.com/zhengtu2015/p/5251469.html
Copyright © 2011-2022 走看看