我正在尝试创建一个从手机加载联系人列表的应用程序,但这需要花费大量时间根据联系人的数量。我想在后台运行加载联系人列表,这样它不会减慢应用程序的速度。 我正在使用以下函数加载联系信息。
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 :(得分:1)
执行后台任务有很多方法。
AsyncTask
:老式=> doc Handler
:post 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)
您可以使用以下几个决定:
AsyncQueryHelper - 它是数据库请求的包装类。它是一个抽象类,因此您必须创建自己的实现。看到这个链接: https://gist.github.com/EugeneShapovalov94/9944560e42a080d35d6ce06fb17e41c4
CursorLoader - 这是基于加载器的决定。您应该实现加载程序回调以启动它,接收结果并重置它。看到这个链接: http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html
RxJava - 这是最困难的决定,但它是最灵活的。您可以修改observable / single以从源(filter,map)获得不同的结果。你应该订阅Scheduler.IO并观察AndroidSchedulers.mainThead。
答案 6 :(得分:0)
如果您想获取并显示您的联系人,可以使用CursorLoader
查询ContentResolver并返回一个Cursor对象。
因此,您需要在自己的类中实现LoaderManager.LoaderCallbacks
接口。您必须实施onCreateLoader
(您将查询ContentResolver
),onLoadFinished
和onLoaderReset
方法。
然后你可以用[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类
在后台运行代码