LoaderManager的使用

在数据库操作中,只有查询是比较难的,因为这个操作数据过多的话很可能会造成主线程阻塞。以前我总是把查询数据的方法放在新开的子线程中来进行,今天发现了一个好方法。

并且这个方法不管在Acitivity里还是在Fragment都很好用。

首先呢要声明一个LoaderManager对象,

然后要初始化LoaderManager,第一个参数id,可以随便写,第二个参数是可选项,第三个是回调方法

然后需要实现callback接口public class MainActivity extends Activity implements LoaderCallbacks<Cursor>

会生成三个方法,在具体代码中会说明方法的作用,

最后还要写一个类来实现一个异步的Loader,这里需要注意的是这个继承的类必须是静态的

static class MyAsycLoader extends AsyncTaskLoader<Cursor>

java代码

package com.example.loader;

import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.app.Activity;
import android.app.LoaderManager;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.AsyncTaskLoader;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Loader;
import android.database.Cursor;
import android.widget.Toast;

public class MainActivity extends Activity implements LoaderCallbacks<Cursor> {
    private LoaderManager manager;
    static ContentResolver resolver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        resolver = getContentResolver();
        manager = getLoaderManager();
        manager.initLoader(1001, null, this);
        // 调用这个方法必须在主线程中,如果数据发生了改变,显示的数据会随之改变
        manager.getLoader(1001).onContentChanged();

    }

    // 返回要查询的对象
    // 完成查询操作,把结果返回给调用者
    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
        // TODO Auto-generated method stub
        return new MyAsycLoader(this);
    }

    // 更新ui操作
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor query) {
        while (query.moveToNext()) {
            System.out.println(query.getString(0));
            Toast.makeText(this, query.getString(0), 0).show();
        }

    }

    @Override
    public void onLoaderReset(Loader<Cursor> arg0) {
        // TODO Auto-generated method stub

    }

    // 异步的loader
    // 这个类必须为static
    static class MyAsycLoader extends AsyncTaskLoader<Cursor> {

        public MyAsycLoader(Context context) {
            super(context);
            // TODO Auto-generated constructor stub
        }

        // 执行查询操作
        @Override
        public Cursor loadInBackground() {
            Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            // 要查询的字段
            String[] projection = { MediaStore.Video.Media.TITLE,
                    MediaStore.Video.Media.DURATION,
                    MediaStore.Video.Media.SIZE, MediaStore.Video.Media.DATA };

            Cursor query = resolver.query(uri, projection, null, null, null);
            return query;
        }
        //必须实现
        @Override
        protected void onStartLoading() {
            // TODO Auto-generated method stub
            super.onStartLoading();
            // 如果内容发生改变,通知调用者
            if (takeContentChanged()) {
                forceLoad();
            }
        }

    }

}

这里更新ui的操作只是弹出了吐司。

下面来看在Fragment里的操作,因为Fragment的生命周期比较复杂

package com.mingrikeji.fragment;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.app.LoaderManager.LoaderCallbacks;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.videoplayer.R;
import com.mingrikeji.bean.VideoBean;
import com.mingrikeji.utils.PlayerUtils;

/**
 * A simple {@link android.support.v4.app.Fragment} subclass.
 *
 */
public class TwoFragment extends ListFragment implements
        LoaderCallbacks<Cursor> {
    // 声明LoaderManager对象
    private LoaderManager loader;
    // 声明适配器对象
    private VideoAdapter mAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        // 获得LoaderManager
        loader = getLoaderManager();
        // 实例化VideoAdapter
        mAdapter = new VideoAdapter();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // 初始化一个Loader,并注册回调事件,第一个参数id,可以随便写,第二个参数是可选项,第三个是回调方法
        loader.initLoader(0, null, this);
        return inflater.inflate(R.layout.fragment_two, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onActivityCreated(savedInstanceState);
    }

    @Override
    public void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);
        VideoBean video = (VideoBean) mAdapter.getItem(position);
        Toast.makeText(getActivity(), video.getPath(), 0).show();
    }

    class VideoAdapter extends BaseAdapter {
        private List<VideoBean> list;

        // 绑定数据
        public void bindData(List<VideoBean> list) {
            this.list = list;
        }

        // 获取显示列表的总数
        @Override
        public int getCount() {
            return list.size();
        }

        // 返回当前位置的对象
        @Override
        public Object getItem(int arg0) {
            return list.get(arg0);
        }

        // 返回当前位置的id
        @Override
        public long getItemId(int arg0) {
            return arg0;
        }

        // 返回要显示的view对象
        @Override
        public View getView(int position, View arg1, ViewGroup arg2) {
            // 声明view
            View v = null;
            // 声明ViewHolder对象
            ViewHolder viewHolder = null;
            // 判断是否有缓存,有的话就可以用缓存,没有的话重新把视图对象转化成view对象
            if (arg1 != null) {
                v = arg1;
                viewHolder = (ViewHolder) v.getTag();
            } else {
                // 把布局文件转化成视图对象
                v = View.inflate(getActivity(), R.layout.item_videolist, null);
                // 实例化ViewHolder
                viewHolder = new ViewHolder();
                // 实例化标题textview
                viewHolder.tv_title = (TextView) v
                        .findViewById(R.id.item_videolist_title);
                // 实例化大小textview
                viewHolder.tv_size = (TextView) v
                        .findViewById(R.id.item_videolist_size);
                // 实例化时间textview
                viewHolder.tv_time = (TextView) v
                        .findViewById(R.id.item_videolist_time);
                // 放入tag对象里
                v.setTag(viewHolder);
            }
            // 根据位置设置标题
            viewHolder.tv_title.setText(list.get(position).getTitle());
            // 根据位置设置时间,和文件长度
            String size = PlayerUtils.getTime(list.get(position).getTime());
            String time = Formatter.formatFileSize(getActivity(),
                    Long.parseLong(list.get(position).getSize()));
            viewHolder.tv_time.setText(time);
            viewHolder.tv_size.setText(size);
            return v;
        }
    }

    /**
     * ViewHolder对象
     *
     * @author Administrator
     *
     */
    static class ViewHolder {
        //标题
        TextView tv_title;
        //长度
        TextView tv_size;
        //时间
        TextView tv_time;

    }
    //返回要查询的对象
    //完成查询操作,把结果返回给调用者
    @Override
    public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
        Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
        // 要查询的数据
        String[] projection = { MediaStore.Video.Media.TITLE,
                MediaStore.Video.Media.DURATION, MediaStore.Video.Media.SIZE,
                MediaStore.Video.Media.DATA };

        CursorLoader cu = new CursorLoader(getActivity(), uri, projection,
                null, null, null);
        return cu;
    }
    //更新ui操作
    @Override
    public void onLoadFinished(Loader<Cursor> arg0, Cursor query) {
        // TODO Auto-generated method stub
        List<VideoBean> list = new ArrayList<VideoBean>();
        while (query.moveToNext()) {
            VideoBean video = new VideoBean();
            // 设置bean
            video.setTitle(query.getString(0));
            video.setTime(query.getString(1));
            video.setSize(query.getString(2));
            video.setPath(query.getString(3));
            list.add(video);
        }
        // 发送数据到适配器
        mAdapter.bindData(list);
        // 设置适配器
        setListAdapter(mAdapter);
    }

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

    }

}

在Fragment里我们用到了

CursorLoader ,这个方法同样的不会造成ANR,就不用写异步的loader了。
CursorLoader 这个方法有两个构造方法,这里用的是第一个,第二个是直接可以传递上下文,然后一个一个的设置参数。
 
时间: 2024-08-27 11:44:35

LoaderManager的使用的相关文章

LoaderManager使用详解(二)---了解LoaderManager

了解LoaderManager 这篇文章将介绍LoaderManager类,这是该系列的第二篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四:实例:AppListLoader 注意: 要了解这一LoaderManager这部分知识,要求对Loaders如何工作有基本了解.Loaders的实现将在下一篇文章中涵盖.现在你只需要将Loaders看成一个简单.字包含的对象.该对象特性包括:1.在一个单独线程载入数据:2.监测底层数据源,当探测到有改变

LoaderManager与CursorLoader用法

一.基本概念 1.LoaderManager LoaderManager用来负责管理与Activity或者Fragment联系起来的一个或多个Loaders对象. 每个Activity或者Fragment都有唯一的一个LoaderManager实例(通过getLoaderManager()方法获得),用来启动,停止,保持,重启,关闭它的Loaders,这些功能可通过调用initLoader()/restartLoader()/destroyLoader()方法来实现. LoaderManager

深入源码解析Android中Loader、AsyncTaskLoader、CursorLoader、LoaderManager

如果对Loader.AsyncTaskLoader.CursorLoader.LoaderManager等概念不明白或不知道如何使用Loader机制,可参见博文Android中Loader及LoaderManager的使用(附源码下载).本文主要通过研究Loader及其子类的生命周期的方式来对Loader及其子类.LoaderManager的源码进行研究. Loader是靠LoaderManager管理的,LoaderManager可以同时管理多个Loader,即LoaderManager与Lo

Android中Loader及LoaderManager的使用(附源码下载)

managedQuery方法的缺陷 Loader是用来更好地加载数据的,在我们谈论Loader之前,我们先研究一下Activity的managedQuery方法,该方法也是用于在Activity中加载数据的.在Android 3.0之前的版本中,我们如果想在Activity中通过ContentResolver对ContentProvider进行查询,我们可以方便的调用Activity的managedQuery方法,该方法的源码如下: @Deprecated public final Cursor

LoaderManager使用详解(三)---实现Loaders

这篇文字将介绍Loader<D>类,并且介绍自定义Loader的实现.这是本系列的第三篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四:实例:AppListLoader 重中之重,如果你还没有读过前面两篇文章,我建议你在深入之前先读一读那两篇文章.先简短的总结一下这篇博客覆盖了什么内容.Loader之前的世界(第一篇)描述了Android3.0之前的数据载入方法和在UI主线程中执行的冗长的查询操作.这些UI非友好的API导致了应用响应变差.总

LoaderManager使用详解(四)---实例:AppListLoader

实例:AppListLoader 这篇文章将是我的第四篇,也就是最后一篇该系列的文章.请在评论里面告诉我他们是否有用.前面几篇文章的链接如下: 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四:实例:AppListLoader 应大众的要求,我已经写了一个示例应用演示如何正确的实现一个自定义Loader.应用名称为:AppListLoader,它是一个演示应用,可以查询并列出你的Android设备上所有已安装的应用程序.应用已经修改,重新构建(没有bug

LoaderManager使用具体解释(三)---实现Loaders

这篇文字将介绍Loader<D>类,而且介绍自己定义Loader的实现.这是本系列的第三篇文章. 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四:实例:AppListLoader 重中之重,假设你还没有读过前面两篇文章,我建议你在深入之前先读一读那两篇文章.先简短的总结一下这篇博客覆盖了什么内容.Loader之前的世界(第一篇)描写叙述了Android3.0之前的数据加载方法和在UI主线程中运行的冗长的查询操作.这些UI非友好的API导致了应用响应变

Android应用开发:LoaderManager在Activity/Fragment中的使用分析

LoaderManager 外部接口initLoader:起始 public <D> Loader<D> initLoader(int id, Bundle args, LoaderManager.LoaderCallbacks<D> callback) { if (mCreatingLoader) { throw new IllegalStateException("Called while creating a loader"); } Loade

LoaderManager使用详解(一)---没有Loader之前的世界

来源: http://www.androiddesignpatterns.com/2012/07/loaders-and-loadermanager-background.html 感谢作者Alex Lockwood的努力,让我们看到如此精彩的文章. 第一部分 没有Loader之前的世界 这一部分将对Loaders和LoaderManager做一个简短的介绍.第一节将在Android3.0之前如何载入数据,指出其缺陷.第二节讲述每个类的目的,以及它们异步载入数据的能力. 这篇文章是有关Loade

LoaderManager使用具体解释(四)---实例:AppListLoader

实例:AppListLoader 这篇文章将是我的第四篇,也就是最后一篇该系列的文章.请在评论里面告诉我他们是否实用.前面几篇文章的链接例如以下: 一:Loaders之前世界 二:了解LoaderManager 三:实现Loaders 四:实例:AppListLoader 应大众的要求.我已经写了一个演示样例应用演示怎样正确的实现一个自己定义Loader.应用名称为:AppListLoader,它是一个演示应用.能够查询并列出你的Android设备上全部已安装的应用程序. 应用已经改动.又一次构