android的设计之中,任何耗时的操作都不能放在UI主线程之中。所以类似于网络操作等等耗时的操作都需要使用异步的实现。而在ContentProvider之中,也有可能存在耗时的操作(当查询的数据量很大的时候),这个时候我们也需要使用异步的调用来完成数据的查询。
当使用异步的query的时候,我们就需要使用LoaderManager了。使用LoaderManager就可以在不阻塞UI主线程的情况下完成数据的加载。
1)获取loaderManger:activity.getLoaderManager()
2)loaderManager的事件回调接口, LoaderManager.LoaderCallbacks<D>
下面是一个demo,从contentprovider中query数据添加到listview中,是异步执行的。
MySQLiteOpenHeleper.java:
package com.app.loadermanager; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class MySQLiteOpenHelper extends SQLiteOpenHelper { public static final String db_name = "test.db3"; public static final int version = 1; public MySQLiteOpenHelper(Context context) { super(context, db_name, null, version); } @Override public void onCreate(SQLiteDatabase db) { String create_sql = "create table tb_student(_id integer primary key autoincrement,name varchar(20),age integer)"; db.execSQL(create_sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
MyContentProvider.java
package com.app.loadermanager; import android.content.ContentProvider; import android.content.ContentUris; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; public class MyContentProvider extends ContentProvider { private MySQLiteOpenHelper helper = null; private static final UriMatcher matcher = new UriMatcher( UriMatcher.NO_MATCH); private static final int students = 1; static { matcher.addURI("com.app.contentprovider", "tb_student", students); } @Override public int delete(Uri arg0, String arg1, String[] arg2) { return 0; } @Override public String getType(Uri arg0) { return null; } @Override public Uri insert(Uri uri, ContentValues values) { SQLiteDatabase db = helper.getWritableDatabase(); int flag = matcher.match(uri); switch (flag) { case students: long id = db.insert("tb_student", null, values); return ContentUris.withAppendedId(uri, id); } return null; } @Override public boolean onCreate() { helper = new MySQLiteOpenHelper(this.getContext()); return true; } @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase db = helper.getWritableDatabase(); Cursor cursor=db.query("tb_student", projection, selection, selectionArgs, null, null, null); return cursor; } @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { return 0; } }
MainActivity.java:
package com.app.loadermanager; import java.util.ArrayList; import android.annotation.SuppressLint; import android.app.Activity; import android.app.LoaderManager; import android.content.CursorLoader; import android.content.Loader; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; @SuppressLint("NewApi") public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<Cursor> { LoaderManager manager = null; ListView listView = null; @SuppressLint("NewApi") @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listView = (ListView) this.findViewById(R.id.listview); manager = this.getLoaderManager(); manager.initLoader(1000, null, this); } @Override public Loader<Cursor> onCreateLoader(int id, Bundle bundle) { CursorLoader loader = new CursorLoader(this, Uri.parse("content://com.app.contentprovider"), null, null, null, null); return loader; } @Override public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { ArrayList<String> al = new ArrayList<String>(); while (cursor.moveToNext()) { String name = cursor.getString(cursor.getColumnIndex("name")); al.add(name); } ArrayAdapter adapter=new ArrayAdapter(this,android.R.layout.simple_list_item_1,al); listView.setAdapter(adapter); adapter.notifyDataSetChanged(); } @Override public void onLoaderReset(Loader<Cursor> loader) { } }