Android Loader 机制

简介

  Loaders机制是在Android3.0 版本之后引入的异步加载数据的方法,能解决长时间加载数据的问题

特点

  1.适用于任何Activity和Fragment

  2.提供了异步加载数据的机制

  3.检测数据源,当数据源的内容改变是他们能够传递新的结果

相关API

  LoaderManager:管理Loader,每个Activity或Fragment都对应一个LoaderManager

  LoaderCallbacks:包含和Loader相关的回调方法

  AsyncTaskLoader:抽象类,提供异步加载的方法

  Cursors Loader:AsyncTaskLoader的子类,提供游标数据的加载,本地数据库数据的加载

案例:使用Loader加载本地联系人:

package com.hejun.loader;

import android.Manifest;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<Cursor> {

    //绑定资源
    @BindView(R.id.listView)
    ListView listView;
    @BindView(R.id.ed)
    EditText ed;
    private SimpleCursorAdapter cursorAdapter;
    private LoaderManager loaderManager;
    private String content;
    private Uri contentUri;
    private CursorLoader cursorLoader;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);
        requestPermission();
        //获取loaderManager对象
        loaderManager = getSupportLoaderManager();
        //初始化Loader 参数1 ID 参数2 传递的参数 参数3 LoaderCallbacks 回调接口
        loaderManager.initLoader(0, null, this);
        cursorAdapter = new SimpleCursorAdapter(this,
                android.R.layout.activity_list_item,
                null,
                new String[]{ContactsContract.Contacts.DISPLAY_NAME},
                new int[]{android.R.id.text1},
                CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
        listView.setAdapter(cursorAdapter);
        ed.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                content = s.toString();
                //重新加载Loader
                loaderManager.restartLoader(0,null,MainActivity.this);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }

    /**
     * 创建Loader对象
     *
     * @param i
     * @param bundle
     * @return
     */
    @NonNull
    @Override
    public Loader<Cursor> onCreateLoader(int i, @Nullable Bundle bundle) {
        contentUri = ContactsContract.Contacts.CONTENT_URI;
        if (!TextUtils.isEmpty(content)){
            contentUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_FILTER_URI,Uri.encode(content));

        }
        cursorLoader = new CursorLoader(this, contentUri, null, null, null, null);
        return cursorLoader;
    }

    /**
     * 在UI线程中运行,加载数据完成后,更新UI
     *
     * @param loader
     * @param cursor
     */
    @Override
    public void onLoadFinished(@NonNull Loader<Cursor> loader, Cursor cursor) {
        //在主线程中完成, 切换cursorAdapter中的游标
        cursorAdapter.swapCursor(cursor);
    }

    /**
     * 重置Loader
     *
     * @param loader
     */
    @Override
    public void onLoaderReset(@NonNull Loader<Cursor> loader) {
        //销毁游标
        cursorAdapter.swapCursor(null);
    }
    //动态申请权限
    private void requestPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_CONTACTS)
                != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_CONTACTS},
                    0);//申请权限


        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode) {
            case 0:
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    return;
                } else {
                    finish();
                }
                break;
        }
    }
}

自定义Loader:使用Loader加载自定义数据类型

  步骤:

  1.继承AsycnTaskLoader类

  2.实现loadInBackground方法

  3.使用LoadManager初始化Loader  

  4.在LoaderCallbacks接口的OnCreateLoader方法中返回自定义Loader

案例:从网上加载用户信息(name password)

用户类

class Userbean {

    private String name;

    private String password;

    public Userbean(String name, String password) {
        this.name = name;
        this.password = password;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

自定义Loader

package com.hejun.loader;

import android.content.Context;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.AsyncTaskLoader;

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

/**
 * 自定义Loader,加载UserBean数据集合
 */
public class LoaderUser extends AsyncTaskLoader<List<Userbean>> {

    public LoaderUser(@NonNull Context context) {
        super(context);
    }

    @Override
    protected void onStartLoading() {
        super.onStartLoading();
        //Loader开始执行后,强制调用loadInBackground()方法
        if (isStarted()){
            forceLoad();
        }
    }

    /**
     * 在子线程中加载数据
     * @return
     */
    @Nullable
    @Override
    public List<Userbean> loadInBackground() {
        //模拟从网上获取数据
        List<Userbean> users = new ArrayList<>();
        users.add(new Userbean("zhangsan","123456"));
        users.add(new Userbean("lisi","123456"));
        users.add(new Userbean("wangwu","123456"));
        users.add(new Userbean("zhaoliu","123456"));
        return users;
    }
}

MainActivity:

package com.hejun.loader;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.app.AppCompatActivity;
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 java.util.ArrayList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

public class Main2Activity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<List<Userbean>> {

    @BindView(R.id.listView)
    ListView listView;

    private List<Userbean> list = new ArrayList<>();
    private Adapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        ButterKnife.bind(this);
        LoaderManager loaderManager = getSupportLoaderManager();
        loaderManager.initLoader(0, null, this);
        adapter = new Adapter(this);
        listView.setAdapter(adapter);
    }

    @NonNull
    @Override
    public Loader<List<Userbean>> onCreateLoader(int i, @Nullable Bundle bundle) {
        //返回自定义Loader
        return new LoaderUser(this);
    }

    @Override
    public void onLoadFinished(@NonNull Loader<List<Userbean>> loader, List<Userbean> uerbeanList) {
        adapter.addUsers(uerbeanList);
        adapter.notifyDataSetChanged();
    }

    @Override
    public void onLoaderReset(@NonNull Loader<List<Userbean>> loader) {

    }

    class Adapter extends BaseAdapter {

        private Context context;

        private List<Userbean> users = new ArrayList<>();

        public Adapter(Context context) {
            this.context = context;
        }

        public void addUsers(List<Userbean> userList) {
            users.addAll(userList);
            notifyDataSetChanged();
        }

        @Override
        public int getCount() {
            return users.size();
        }

        @Override
        public Userbean getItem(int position) {
            return users.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder viewHolder = null;
            if (convertView == null) {
                convertView = LayoutInflater.from(context).inflate(R.layout.item, parent, false);
                viewHolder = new ViewHolder(convertView);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            Userbean userbean = users.get(position);
            viewHolder.name.setText(userbean.getName());
            viewHolder.password.setText(userbean.getPassword());
            return convertView;
        }

        class ViewHolder {
            @BindView(R.id.name)
            TextView name;
            @BindView(R.id.password)
            TextView password;

            ViewHolder(View view) {
                ButterKnife.bind(this, view);
            }
        }
    }
}

总结

  可以用CursorsLoader加载数据库,ContentProvider数据

  对于自定义数据类型,可以自定义Loader来实现

  

原文地址:https://www.cnblogs.com/conglingkaishi/p/10097119.html