Android 片段内的线程

Android 片段内的线程,android,multithreading,android-fragments,Android,Multithreading,Android Fragments,我有一个应用程序使用了一个带有视图寻呼机的片段。我查询android联系人数据库(这应该很快),以获取每个联系人的主要号码,并显示在列表视图中。问题是,这似乎需要一些时间。我尝试在onCreateView和“更新”中使用线程和异步任务,或者为联系人列表设置适配器。当我这样做时,我会遇到一些错误: 无法在未调用Looper.prepare()的线程内创建处理程序 我尝试使用Looper.prepare(),但它仍然会崩溃 所以我加入了一个处理程序,但当人们启动我的应用程序时会出现延迟 final

我有一个应用程序使用了一个带有视图寻呼机的片段。我查询android联系人数据库(这应该很快),以获取每个联系人的主要号码,并显示在列表视图中。问题是,这似乎需要一些时间。我尝试在onCreateView和“更新”中使用线程和异步任务,或者为联系人列表设置适配器。当我这样做时,我会遇到一些错误:

无法在未调用Looper.prepare()的线程内创建处理程序

我尝试使用Looper.prepare(),但它仍然会崩溃

所以我加入了一个处理程序,但当人们启动我的应用程序时会出现延迟

final Runnable setupView = new Runnable() {
        @Override
        public void run() {
            contactos  = con.getContactSearch("");
            setupContacts();
        }
    };
其中: getContactSearch:

public HashMap<String, ContactInfo> getContactSearch(String _where)
     {
         contactInfo = new HashMap<String, ContactInfo>();
         Cursor cursor = null ;
         if(_where.length()==0)
         {
            cursor = getContacts();
         }else
         {
             cursor = getContactsFilter(_where);
         }
         try
         {
         while (cursor.moveToNext()) {
              String id = cursor.getString(cursor
                      .getColumnIndex(ContactsContract.Contacts._ID));
              if(!contactInfo.containsKey(id))
              {

                  String displayName = cursor.getString(cursor
                          .getColumnIndex(ContactsContract.Data.DISPLAY_NAME));
                //obtenemos el telefono principal
                 //String number = "" ;//getPrimaryNumber(id);
                  ContactInfo ci = new ContactInfo(displayName,"",id);
                  contactInfo.put(id,ci);
              }
            }
            getPrimaryNumbers();


         }finally
         {
             cursor.close();
         }
         return contactInfo;
     }
我如何异步执行此操作?我想知道如果我只在onCreate()中搜索联系人会发生什么,如果它比onCreateView快,ListView将为空。这样做“有效”,但有很大的滞后。 如何优化此过程?

您的setupContacts()方法会处理UI内容,这在UI线程之外是无法完成的。您必须创建一个新的Runnable并将其发布到UI线程视图活动中。runOnUiThread()或view.post()

如果这看起来像是令人恼火的陈词滥调,那就是。创建的目的是简化在后台做事情然后发布到UI线程的模型

使用AsyncTasks的一个问题是,在任务完成时,启动它的活动可能已死亡。如果是配置更改(例如设备旋转),您仍然需要数据,但asynctask指向一个死引用。在最好的情况下什么也不会发生,在最坏的情况下,您会得到一个空指针异常。这确实令人沮丧,因为片段可以很好地经受住这些配置更改


是为了解决这个问题而创建的。API文档中有一个AsyncTaskLoader示例,它在获取一些数据后填充适配器。

使用
LoaderManager
来管理此示例。在循环中获取联系人总是非常慢。如果您将某些信息显示为ListView的一部分,而该行的其他部分的获取速度比联系人信息快,我建议您延迟加载速度较慢的部分。我想我的问题是使用CUrsorLoader,我现在使用getcontentresolver,也许我将所有内容移动到Loader,现在似乎快了一点:)我使用这个网站来使用AsynTaskLoader,因为使用Loader会让人困惑,这会有所帮助
    mAdapter = new DialerContactsAdapter(contactos,getActivity());
        listaContactos.setAdapter(mAdapter);
        listaContactos.setFastScrollEnabled(true);
        listaContactos.setOnScrollListener(new OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                switch (scrollState) {
                case OnScrollListener.SCROLL_STATE_IDLE:
                mAdapter.mBusy = false;
                mAdapter.notifyDataSetChanged();
                break;
                case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:
                    mAdapter.mBusy = false;
                    mAdapter.notifyDataSetChanged();
                break;
                case OnScrollListener.SCROLL_STATE_FLING:
                    mAdapter.mBusy = true;
                break;
                }
            }

            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                // TODO Auto-generated method stub

            }
        });