2017-07-18 34 views
1

我正試圖從手機中加載聯繫人列表的應用程序,但這需要大量的時間根據聯繫人的數量。我想在後臺運行加載聯繫人列表,以便它不會減慢應用程序的速度。 我正在使用以下函數來加載聯繫人信息。如何在android的後臺運行一段代碼?

void loadContacts() { 
    ContentResolver contentResolver=getContentResolver(); 
    Cursor cursor=contentResolver.query(ContactsContract.Contacts.CONTENT_URI,null,null,null,null); 
    if(cursor.getCount() > 0) { 
     while (cursor.moveToNext()) { 
      String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); 
      String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); 
      Bitmap photo = retrieveContactPhoto(id); 
      int hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER))); 
      String phoneNumber = null; 
      if (hasPhoneNumber > 0) { 
       Cursor cursor2 = contentResolver.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, 
         ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = ?", new String[]{id}, null); 
       while (cursor2.moveToNext()) { 
        String ph = cursor2.getString(cursor2.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); 
        phoneNumber = ph.replaceAll("\\s", ""); 
        System.out.println(phoneNumber); 
       } 
       cursor2.close(); 
      } 
      if(phoneNumber==null) 
       continue; 
     } 
    } 
    cursor.close(); 
} 
+0

可以使用asyncktask使代碼在後臺運行 –

+0

'AsyncTask'將讓你在後臺線程 –

+2

使用'CursorLoader'運行的東西;這比使用'AsyncTask'更強大。請參閱[本教程](https://developer.android.com/training/contacts-provider/retrieve-names.html),它正是您想要的。 –

回答

0

你需要使用一個Loader來解決你的查詢。使用裝載機給你一些好處。其中之一是:如果用戶旋轉手機並重新啓動Activity,則加載器被保留(不再需要查詢數據庫,因爲對加載器的遊標引用仍將可用),即加載器是生命週期知道的。您需要實現

LoaderManager.LoaderCallbacks<Cursor> 

這樣

MyActivity extends AppCompatActivity implements 
    LoaderManager.LoaderCallbacks<Cursor>{ 

     @Override 
     public Loader<Cursor> onCreateLoader(int id, Bundle args) { 
        //return a new instance of CursorLoader 

          return new CursorLoader(this) { 
            //this reference will be preserved when activity rotates 
            Cursor myCursor; 


            @Override 
            protected void onStartLoading() { 
             super.onStartLoading(); 

             //myCursor will be null when activity is starting for the first time 
             if (myCursor== null) 
               forceLoad(); 
             else 
              deliverResult(myCursor); 
     } 

            @Override 
            public Cursor loadInBackground() { 
             //make your database query here 

             myCursor = getContext().getContentResolver().query() 
             return myCursor; 

             } 

           } 


         } 

     @Override 
     public void onLoadFinished(Loader<Cursor> loader, Cursor data) { 

         //bind your Cursor to your activity view 

         } 


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

         } 


      } 

欲瞭解更多信息,結帳我Udacity Nanodegree代碼here行272 - 338說明它更好。

0

簡單的方法就是把它的工作線程,你應該實現Runnable接口寫在run方法的邏輯。

否則,你也可以去的AsyncTask這樣做的工作 - check this link

0

任何你所寫的(或)中寫道doInBackground方法的AsyncTask類中調用烏爾法在後臺運行。它運行了不同的線程無連接UI。異步

樣品

 class MyAsync extends AsyncTask<Void, Integer, String> 
     { 

      protected void onPreExecute(){ 

      } 

      protected String doInBackground(Void...arg0) { 
       //do wht need in background 
    `   loadContacts(); 
       return " "; 
      } 


     } 

這樣稱呼它在你的活動:

new MyAsync().execute(); 
+0

你是否嘗試過這個 –

0

如果您使用科特林與安口,你可以做到這一點很容易

doAsync { 

//code to run in the background 

uiThread { 

//code to run on the ui (like changing a text or something) 

}} 
0

你可以做它與這樣一個異步任務:

private class yourMethod extends AsyncTask<String, Void, String> { 
    public yourMethod() { 

    } 

    @Override 
    protected String doInBackground(String... params) { 
     return null; 
    } 

    @Override 
    protected void onPostExecute(String result) { 

    } 

    @Override 
    protected void onPreExecute() { 

    } 

    @Override 
    protected void onProgressUpdate(Void... values) { 
    } 
} 
0

您可以使用多個決定:

  1. AsyncQueryHelper - 它是數據庫請求包裝類。它是一個抽象類,所以你必須創建你自己的實現。看到這個鏈接: https://gist.github.com/EugeneShapovalov94/9944560e42a080d35d6ce06fb17e41c4

  2. CursorLoader - 這是基於加載器的決定。您應該實現加載器回調以啓動它,接收結果並重置它。看到這個鏈接: http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html

  3. RxJava - 這是最困難的決定,但它是最靈活的。您可以修改observable/single以從源(過濾器,映射)獲取不同的結果。您應該訂閱Scheduler.IO並遵守AndroidSchedulers.mainThead。

1

有很多方法可以做後臺任務。

  • AsyncTask:老式=>doc
  • Handlerpost about that
  • Thread:經典(Java的方式)
  • RxJava:我最喜歡=>doc
  • ...

例與RxJavaKotlin(第2版):

Observable 
      .fromCallable<String> { 
       // Do the job here 
       "the result" 
      } 
      .subscribeOn(Schedulers.computation()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe { result -> 
       // use the result! 
      } 
0

如果你想獲得並顯示您的聯繫人可以使用CursorLoader

查詢ContentResolver的,並返回一個光標對象。

所以你需要在你自己的類中實現LoaderManager.LoaderCallbacks接口。您必須執行以及onCreateLoader(您將查詢ContentResolver),onLoadFinishedonLoaderReset方法。 然後你可以使用[getLoaderManager().initLoader(int id, Bundle args, LoaderCallbacks<D> callback);](https://developer.android.com/reference/android/app/LoaderManager.html#initLoader(int,android.os.Bundle,android.app.LoaderManager.LoaderCallbacks)方法執行CursorLoader。

如果您只想獲取聯繫人而不顯示它們,則可以使用AsyncTask,這樣您可以輕鬆地執行後臺操作。

使用AsyncTask,您將需要創建一個內部類,該類擴展了AsyncTask<Params, Progress, Result>以及至少doInBackground(Params... params)方法(您將在其中編寫後臺代碼)。 您將執行調用new YourAsyncTask().execute(Params);的AsyncTask bt。

0

Android推薦的方法是使用Asynctask。後臺執行代碼doInBackground()。 Asynctasks通過使用私有內部類和實現doInBackground()裏面,然後通過使用new YourAsyncTask.execute()

另一種流行的方式在後臺運行的代碼調用使用RxJava它採用觀測量,是非常靈活的調用。

也可以使用Thread類