2012-04-11 17 views
6

我想知道如何使用CursorLoader在屏幕上填充小部件。所有在线示例仅适用于使用适配器,并且这很有用。我需要的是从游标和UI线程更新屏幕中视图的可靠方法,并且由于StaleDataException或光标突然被停用,有时不会崩溃。这是我目前的方法,但我仍然收到来自用户的一些崩溃报告。从onLoadFinished中的光标填充小部件()

@Override 
    public Loader<Cursor> onCreateLoader(int id, Bundle arg1) { 
     CursorLoader loader = null; 

     switch (id) { 
      case LOADER_ID_DATA: 
       loader = new CursorLoader(...); 
       break; 
     } 

     return loader; 
    } 

    @Override 
    public void onLoadFinished(Loader<Cursor> loader, final Cursor cursor) { 
     handler.post(new Runnable() { 

      @Override 
      public void run() { 
       if (getActivity() == null) 
        return; 

       updateView(cursor); 
      } 
     }); 
    } 

    @Override 
    public void onLoaderReset(Loader<Cursor> arg0) { 
    } 

一个解决办法是,直接检索所有光标领域内onLoadFinished和他们都传递到处理程序来填充UI线程上的小窗口。但这很丑陋,因为我可能在游标中有很多值。我很想找到一个可靠的无碰撞方式来处理这一切。

+0

“一种解决方案是直接在onLoadFinished中检索所有的游标字段,并将它们全部传递给处理程序,以在UI线程上填充小部件” - onLoadFinished()'在主应用程序线程上被调用。 – CommonsWare 2012-04-11 12:33:03

+0

@CommonsWare据我所知,onLoadFinished不会在主UI线程上调用。如果您在Reto Meier编写的android-protips_location源代码中寻找示例,他会使用处理程序来使用值填充小部件。他上面的onLoadFinished()的注释是他在主应用程序线程上安排了更新。 – 2012-04-11 12:39:50

+0

来自Reto Meier的引用:“请注意,onLoadFinished不会与主应用程序线程同步,因此我会在加载Cursor的同一线程上提取Cursor值,然后将新的Runnable发布到UI线程,以分配这些新线程值到UI元素“ – 2012-04-11 12:44:20

回答

7

在询问#android-dev SimonVTreadme后,帮助我了解了这一点。

没有什么说明onLoadFinished将在UI线程中调用,所以理论上你应该使用Handler,就像在Reto的书中建议的那样。但是,当使用CursorLoader(这是目前最常见的用例)时,几乎可以保证onLoadFinished将在UI线程中被调用。

+3

“很多”的原因是CursorLoader使用一个AsyncTask来完成它的后台工作,它使用一个静态处理程序来回发,并最终调用onLoadFinished。如果您从主线程调用LoaderManager.initLoader(...),则处理程序也会被保证连接到主线程。为了不把这个Handler附加到主线程上,你必须用Looper创建一个Thread,然后从那里启动Loader。 – SimonVT 2012-05-18 12:09:54