如何在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(); } 

你需要使用一个Loader来解决你的查询。 使用装载机给你一些好处。 其中之一是:如果用户旋转他们的电话,活动重新启动,加载器被保留(不再需要查询数据库,因为你的光标的引用仍然可以在加载器中),即加载器是生命周期知道的。 你需要执行

  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代码这里 272 – 338行解释更好。

有很多方法来做后台任务。

  • AsyncTask :老式=> doc
  • Handler : 发表一下
  • Thread :经典(java风格)
  • RxJava :我的最爱=> doc

使用Kotlin RxJava (版本2)示例:

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

简单的方法是在工作线程上它应该实现Runnable接口与在run方法中编写的逻辑。

否则,你也可以去做AsyncTask做这个工作 – 检查这个链接

如果你和Anko一起使用Kotlin,你可以很容易地做到这一点

 doAsync { //code to run in the background uiThread { //code to run on the ui ( like changing a text or something ) }} 

你可以这样做一个异步任务:

 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) { } } 

你可以使用几个决定:

  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。

如果你想获得并显示你的联系人,你可以使用一个CursorLoader

查询ContentResolver并返回一个Cursor对象。

所以你需要在你自己的类中实现LoaderManager.LoaderCallbacks接口。 您将不得不实现以及onCreateLoader (您将查询ContentResolver ), onLoadFinishedonLoaderReset方法。 然后你可以用[ getLoaderManager().initLoader(int id, Bundle args, LoaderCallbacks<D> callback);执行CursorLoader 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))方法。

如果你只想得到联系人而不显示他们,你可以使用AsyncTask这样你就可以轻松地执行后台操作。

使用AsyncTask,您将需要创建一个扩展AsyncTask<Params, Progress, Result>和至少doInBackground(Params... params)方法(您将在其中编写后台代码)的内部类。 你将执行AsyncTask bt调用new YourAsyncTask().execute(Params);

任何你写(或)在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(); 

Android推荐的方法是使用Asynctask。 doInBackground()代码执行背景。 Asynctasks通过使用一个私有的内部类并在其中实现doInBackground() ,然后通过使用new YourAsyncTask.execute()来调用。

在后台运行代码的另一种流行的方法是使用RxJava,它使用Observables并且非常灵活。

也可以使用Thread类在后台运行代码