zoukankan      html  css  js  c++  java
  • 使用Loader实时查询本地数据库用法

    在看Android的文档时,看到了这么一个东西: Loader

    究竟是什么东西呢?

    Introduced in Android 3.0, loaders make it easy to asynchronously load data in an activity or fragment. Loaders have these characteristics:

    1、They are available to every Activity and Fragment.  //支持Activity和Fragment

    2、They provide asynchronous loading of data.    //可以进行异步下载

    3、They monitor the source of their data and deliver new results when the content changes. //当数据源改变时能及时通知客户端

    4、They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data. //发生configuration change时自动重连接

    Loader技术为我们提供的核心类有:

      • LoaderManager:可以通过Activity或者的Fragment的getLoaderManager()方法得到LoaderManager,用来对Loader进行管理,一个Activity或者Fragment只能有一个LoaderManager。
      • LoaderManager.LoaderCallbacks:用于同LoaderManager进行交互,可以在其中创建Loader对象。
      • AsyncTaskLoader:抽象类,可以进行异步加载数据的Loader,貌似内部也是通过AsynTask实现的,可以通过继承它构建自己的Loader,也可以使用现有的子类,例如异步查询数据库可以使用CursorLoader。

        使用Loader一般可以经过以下步骤:

        1、初始化Loader,可以使用initLoader(intid, Bundle args, LoaderManager.LoaderCallbackscallback);方法进行初始化。
        id:标识Loader的ID,一个Activity或者Fragment只能有一个LoaderManager,但可以有多个Loader,通过ID区 分。在新建Loader时,如果发现已经有相同ID的Loader就会复用该Loader,而不会重新创建。
        args:传给新建Loader的参数。 

        Callback:回调接口。

        2、实现LoaderManager.LoaderCallbacks中的方法,LoaderManager.LoaderCallbacks中需要实现的方法有:
        publicLoader onCreateLoader(int id, Bundle args):创建新的Loader,id为LoaderID,如果已经有相同ID的Loader就会复用该Loader,而不会重新创建。 args为初始化时传递的参数。该方法开始异步查询,并返回一个泛型类,如果是查询数据库可以返回一个CursorLoader,可以返回自定义的Loader。public voidonLoadFinished(Loader loader, D data):异步查询结束的会调用这个方法,并返回查询结果 data。public void onLoaderReset(Loader loader): 当调用Loader.reset()将Loader数据清空时,但在系统销毁Loader时会自动调用Loader.reset()方法,我们一般不需要手动调用,只需要在onLoaderReset方法中,将使用Loader的移除。

        3、使用 restartLoader(intid, Bundle args, LoaderManager.LoaderCallbacks callback)方法进行数据更新,和初始化一个,如果有相同id的Loader存在,会复用Loader,并清空原有Loader中的数据,如果没有就新建一个。这个方法一般使用在需要更新数据时,例如下面例子中,在搜索关键改变时,需要调用这个方法,从新异步查询数据。

    public class CollectDetail extends Activity implements LoaderCallbacks<Cursor> {

    private ListView listview;
    private SimpleCursorAdapter adapter;
    private LoaderManager loaderManager;
    private MySQLiteOpenHelper openHelper;
    private static SQLiteDatabase db;
    private TextView textview_empty;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    //去掉标题栏
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_collect_detail);

    openHelper = new MySQLiteOpenHelper(this);

    //获取DB对象
    db = openHelper.getWritableDatabase();

    listview = (ListView) findViewById(R.id.collect_listView);
    textview_empty = (TextView) findViewById(R.id.textview_collect_empty);//当listview空时显示

    //创建适配器(此时数据为空"null")
    adapter = new SimpleCursorAdapter(this, R.layout.collect_listview_item, null, new String []{"title","nickname","create_time"}, new int[]{R.id.collect_item_title,R.id.collect_item_nickname,R.id.collect_item_create_time},CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);

    listview.setAdapter(adapter);

    listview.setEmptyView(textview_empty);//设置无数据时显示的view

    //获取loadermanager管理者对象
    loaderManager = getLoaderManager();
    //初始化loader

    //第一个参数用于标记一个loader.因为loaderManager可以管理多个loader

    第二个参数"Bundle args"  为查询条件,无条件是为null即可

    第三个参数为初始化loader之后的回调方法(LoaderCallbacks<Cursor>) 一般让此时的Activity去实现


    loaderManager.initLoader(1, null,this );

    //给显示数据的listview设置条目点击监听
    listview.setOnItemClickListener(new OnItemClickListener() {

    @Override
    public void onItemClick(AdapterView<?> parent, View view,
    int position, long id) {
    //跳转到详情界面
    String sql ="select _id,title,nickname,create_time,flag from collect";

    Cursor cursor = db.rawQuery(sql, null);
    cursor.moveToPosition(position);//将cursor游标移动至此position的位置

    //从cursor中获取此条目的详细信息
    String _id = cursor.getString(cursor.getColumnIndex("_id"));
    String title = cursor.getString(cursor.getColumnIndex("title"));
    String nickname = cursor.getString(cursor.getColumnIndex("nickname"));
    String create_time = cursor.getString(cursor.getColumnIndex("create_time"));
    int flag = cursor.getInt(cursor.getColumnIndex("flag"));

    Intent intent = new Intent();
    Bundle bundle =new Bundle();
    bundle.putString("id", _id);
    bundle.putString("title", title);
    bundle.putString("nickname", nickname);
    bundle.putString("create_time", create_time);
    bundle.putInt("flag",flag);
    intent.putExtras(bundle);

    intent.setClass(CollectDetail.this, ItemListview.class);

    startActivity(intent);


    }
    });

    //注册上下文菜,用于 删除此条目,并实施更新listview上的数据
    registerForContextMenu(listview);



    }
    //创建出上下文菜单

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
    ContextMenuInfo menuInfo) {
    getMenuInflater().inflate(R.menu.collect_listview, menu);
    super.onCreateContextMenu(menu, v, menuInfo);
    }
    //当上下文菜单中的条目被点击时,删除此条目,并重启loader
    @Override
    public boolean onContextItemSelected(MenuItem item) {

    AdapterContextMenuInfo menuInfo = (AdapterContextMenuInfo) item.getMenuInfo();
    int position = menuInfo.position;

    Cursor cursor = adapter.getCursor();//从适配器中获取到cursor

    cursor.moveToPosition(position);
    String _id = cursor.getString(cursor.getColumnIndex("_id"));//获取到此位置信息的_id更具此_id进行删除操作

    String sql ="delete from collect where _id='"+_id+"'";
    db.execSQL(sql);

    loaderManager.restartLoader(1, null, this);//通过loaderManager重启loader
    return super.onContextItemSelected(item);
    }

    //执行接口回调时,必须要执行的3个方法

    //首先获取到loader对象

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle args) {
       MyAsyncTaskLoader loader = new MyAsyncTaskLoader(this);
        return loader;  
    }

    //当数据加载完成时调用的方法,此时使适配器置换数据为"data"

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor data) {


    adapter.swapCursor(data);

    }

    //当loader重启是调用的方法,此时将适配器中的数据置换为空

    @Override
    public void onLoaderReset(Loader<Cursor> loader) {

    adapter.swapCursor(null);

    }

    //写一个类继承AsyncTaskLoader<Cursor>(此类必须定义为静态static类型的)
    public static class MyAsyncTaskLoader extends AsyncTaskLoader<Cursor>{

    public MyAsyncTaskLoader(Context context) {
    super(context);
    // TODO Auto-generated constructor stub
    }
    @Override
    protected void onStartLoading() {
    // TODO Auto-generated method stub
    super.onStartLoading();
      forceLoad();//必须要写此方法,使其能够向下执行loadInBackground
    }

    @Override
    public Cursor loadInBackground() {
    String sql = "select _id,title,nickname,create_time from collect";
    Cursor cursor_collect = db.rawQuery(sql, null);

    return cursor_collect;
    }

    }


    }

  • 相关阅读:
    软考相关试题
    qt中的toUtf8, toLatin1, Local8bit, toUcs4(转)
    qt的中文乱码问题
    《左耳听风》-ARTS-打卡记录-第八周
    杂题
    图论
    基础数据结构
    整除
    同余
    常用数学
  • 原文地址:https://www.cnblogs.com/CallMeMadman/p/4921179.html
Copyright © 2011-2022 走看看