• 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 这个方法有两个构造方法,这里用的是第一个,第二个是直接可以传递上下文,然后一个一个的设置参数。
     
  • 相关阅读:
    Java异常简介
    Java中的接口
    Java中的抽象类
    Java的多态
    关于this
    面向对象的继承方式详解
    1像素边框问题
    HTML5之本地存储SessionStorage
    js数组去重的4个方法
    前端模块化
  • 原文地址:https://www.cnblogs.com/84126858jmz/p/5124252.html
Copyright © 2020-2023  润新知