CursorLoader与ContentProvider结合,实现异步加载

使用CursorLoader和ContentProvider结合,可以实现异步更新数据

CursorLoader介绍

我们知道,Loader一个抽象的类,用于执行异步加载数据,这个Loader对象可以监视数据源的改变和在内容改变后,以新数据的内容改变UI的展示。
它是一个抽象接口,所有需要实现的Loader功能的类都需要实现这个接口,但是如果需要自己开发一个装载机的话,一般并不推荐继承Loader接口,
而是继承它的子类 AsyncTaskLoader ,这是一个以AsyncTask框架执行的异步加载。

Android中还提供了一个 CursorLoader 类,它是 AsyncTaskLoader 的子类,一个异步的加载数据的类,
通过ContentResolver的标准查询并返回一个Cursor 。这个类实现了Loader的协议,以一种标准的方式查询Cursor。
CursorLoader类有两个构造函数, 推荐使用第二个 ,因为使用第一个构造函数,需要还需要通过CursorLoader提供的一些了getXXX()方法设置对应的属性
。两个构造方法如下:

CursorLoader(Context context) 使用此构造方法时,需要使用setXXX()设置相应的属性,否则不能进行查询
CursorLoader(Context context,Uri uri,String[] projection,String selection ,String[] selectionArgs,String sortOrder)shi
CursorLoader 会显示调用ContentProvier 的query方法进行查询,在ContentProvider 的query方法中应该写

如果对Loader机制不太了解的,请看前篇文章
Android Loader机制,实现异步加载数据
这里的ContentProvider为了简便,我就只写了query()方法,写多了不便于理解


/**
 * 使用ContentProvider提供数据的查询功能
 * 
 * @author TerryYang
 * 
 */
public class PersonProvider extends ContentProvider {


    private MyDBHelper dbHelper;


    public PersonProvider(){

    }

    @Override
    public int delete(Uri arg0, String arg1, String[] arg2) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public String getType(Uri arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public Uri insert(Uri arg0, ContentValues arg1) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public boolean onCreate() {
        // 初始化数据持久层
        dbHelper = new MyDBHelper(getContext());
        return false;
    }

    @Override
    public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
            String arg4) {
        // 使用Loader 时,会首先调用query()
        Log.v("LOG","PersonProvider -- query()");
        SQLiteDatabase  db = dbHelper.getReadableDatabase();
        Cursor cursor = db.rawQuery("select *  from person", null);
        return cursor;
    }

    @Override
    public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
        // TODO Auto-generated method stub
        return 0;
    }

}

这里的ContentProvider提供了query(),需要使用ContentProvier的其他方法,自己重写即可。


public class MainActivity extends ActionBarActivity implements
        LoaderCallbacks<Cursor> {

    private ListView mList;
    private CursorAdapter mAdapter;
    private Cursor mCursor;
    private MyDBHelper mDBHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mList = (ListView) findViewById(R.id.id_lv_person);
        mDBHelper = new MyDBHelper(this);
        SQLiteDatabase database = mDBHelper.getReadableDatabase();
        mCursor = database.rawQuery("SELECT * FROM person", null);
        makeCursorAdapter();
        // 使用Loader异步加载数据
        initLoader();
        mList.setAdapter(mAdapter);
    }

    private void initLoader() {
        getLoaderManager().initLoader(0, null, this);

    }

    /**
     * 初始化CursorAdapter
     */
    private void makeCursorAdapter() {
        mAdapter = new CursorAdapter(this, mCursor) {

            // 初次创建View时,找到布局和控件
            @Override
            public View newView(Context context, Cursor cursor, ViewGroup arg2) {
                LayoutInflater inflater = LayoutInflater.from(context);
                View view = inflater.inflate(R.layout.item_list, null);
                ViewHolder holder = new ViewHolder();
                holder.name = (TextView) view.findViewById(R.id.id_tv_name);
                holder.age = (TextView) view.findViewById(R.id.id_tv_age);
                view.setTag(holder);
                return view;
            }

            // 绑定View时,复用布局
            @Override
            public void bindView(View view, Context context, Cursor cursor) {
                ViewHolder holder = (ViewHolder) view.getTag();
                String name = cursor.getString(cursor.getColumnIndex("name"));
                int age = cursor.getInt(cursor.getColumnIndex("age"));
                holder.name.setText(name);
                holder.age.setText(age + "");
            }

            // 在匿名内部类声明内部类需使用final修饰
            final class ViewHolder {
                TextView name;
                TextView age;
            }
        };
    }

    // 插入测试数据
    public void insertData(View view) {
        SQLiteDatabase db = mDBHelper.getWritableDatabase();
        db.execSQL("insert into person(name, age) values('xxx',21)");
        db.close();
        getLoaderManager().restartLoader(0, null, this);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    // 这里 创建CursorLoader的过程,就 包含调用query(),进行查询的过程
    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
        Uri uri = Uri.parse("content://com.terry.Person/person");
        CursorLoader cursorLoader = new CursorLoader(this, uri, null, null,
                null, null);
        return cursorLoader;
    }

    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor cursor) {
        mAdapter.swapCursor(cursor);

    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        mAdapter.swapCursor(null);
    }
}

注意,每次调insert()时,需要使用*restartLoader()重新启动loader,即可显示异步加的数据.

每次使用InsertData插入测试数据时,在ListView显示已经插入的数据.
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值