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 这个方法有两个构造方法,这里用的是第一个,第二个是直接可以传递上下文,然后一个一个的设置参数。
 

 

posted @ 2016-01-12 14:28  aaddrrooiidd  阅读(256)  评论(0编辑  收藏  举报