如何在android的后台运行一段代码?

时间:2017-07-18 07:02:13

标签: android multithreading performance

我正在尝试创建一个从手机加载联系人列表的应用程序,但这需要花费大量时间根据联系人的数量。我想在后台运行加载联系人列表,这样它不会减慢应用程序的速度。 我正在使用以下函数加载联系信息。

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

9 个答案:

答案 0 :(得分:1)

执行后台任务有很多方法。

  • AsyncTask:老式=> doc
  • Handlerpost about that
  • Thread:classic(java style)
  • RxJava:我的最爱=> doc
  • ...

带有RxJava的{​​{1}}(版本2)示例:

Kotlin

答案 1 :(得分:0)

简单的方法是在工作线程上,你应该用运行方法编写的逻辑实现Runnable接口。

否则你也可以去AsyncTask做这项工作 - check this link

答案 2 :(得分:0)

你写的任何东西(或)在doInBackground方法中编写了Asynctask类,调用ur方法在后台运行。它运行不同的线程没有连接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();

答案 3 :(得分:0)

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

doAsync {

//code to run in the background

uiThread {

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

}}

答案 4 :(得分:0)

您可以使用如下的Async任务执行此操作:

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

答案 5 :(得分: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以从源(filter,map)获得不同的结果。你应该订阅Scheduler.IO并观察AndroidSchedulers.mainThead。

答案 6 :(得分:0)

如果您想获取并显示您的联系人,可以使用CursorLoader

  

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

因此,您需要在自己的类中实现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)方法的内部类(您将在其中编写后台代码)。 您将执行AsyncTask bt调用new YourAsyncTask().execute(Params);

答案 7 :(得分:0)

您需要使用Loader来解决您的疑问。使用装载机可以带来一些好处。其中之一是:如果用户旋转手机并重新启动Activity,则保留加载器(不再需要查询数据库,因为对游标的引用仍将在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代码here第272行 - 338更好地解释它。

答案 8 :(得分:0)

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

调用它们

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

也可以使用Thread类

在后台运行代码