android短信小程序之CursorAdapter绑定ListView

同步查询绑定:


mListView = findViewById(R.id.id_containers);
//定义uri
mALL_conversation_uri = Telephony.Threads.CONTENT_URI.buildUpon().appendQueryParameter("simple", "true").build();
//定义projection
//查询要返回的字段
default_all_threads_projection = new String[]{
        Telephony.Threads._ID,
        Telephony.Threads.DATE,
        Telephony.Threads.SNIPPET,
        Telephony.Threads.MESSAGE_COUNT,
        Telephony.Threads.RECIPIENT_IDS,
        Telephony.Threads.SNIPPET,
        Telephony.Threads.SNIPPET_CHARSET,
        Telephony.Threads.READ,
        Telephony.Threads.ERROR,
        Telephony.Threads.HAS_ATTACHMENT,
        Telephony.Threads.RECIPIENT_IDS
};
//限制条件
mSelection = "_id IN (SELECT DISTINCT thread_id FROM sms where "+
        "thread_id NOT NULL UNION SELECT DISTINCT thread_id FROM pdu where "+
        "thread_id NOT NULL  )";
Cursor query = getContentResolver().query(mALL_conversation_uri, default_all_threads_projection, mSelection, null, null);
mListView.setAdapter(new MyAdapter(MainActivity.this,query));

MyAdaper:

class MyAdapter extends CursorAdapter {
    private Context mContext;
    private final LayoutInflater layoutInflater;

    public MyAdapter(Context context, Cursor c) {
        super(context, c);
        mContext = context;
        layoutInflater = LayoutInflater.from(mContext);
    }

    public MyAdapter(Context context, Cursor c, boolean autoRequery, Context mContext, LayoutInflater layoutInflater) {
        super(context, c, autoRequery);
        this.mContext = mContext;
        this.layoutInflater = layoutInflater;
    }

    public MyAdapter(Context context, Cursor c, int flags, Context mContext, LayoutInflater layoutInflater) {
        super(context, c, flags);
        this.mContext = mContext;
        this.layoutInflater = layoutInflater;
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        View view = layoutInflater.inflate(R.layout.test_item, parent, false);
        return view;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView mContent = view.findViewById(R.id.txt_content);
        String string = cursor.getString(cursor.getColumnIndex(Telephony.Threads.SNIPPET));
        mContent.setText(string);
    }
}

上面这种方法容易报错ANR,故慎用!!

异步查询绑定:

MainActivity:

//开始查询短信
public void startQuery(){
    conversationsQuery = new ConversationQuery(getContentResolver());
    conversationsQuery.startQuery(QueryParameter.ALL_CONVERSATION_QUERY_TOKEN,null,QueryParameter.QUERY_ALL_URI,QueryParameter.QUERY_PROJECTION,QueryParameter.QUERY_SELECTION,null,null);
}

//处理增删改查
class ConversationQuery extends AsyncQueryHandler{

    public ConversationQuery(ContentResolver cr) {
        super(cr);

    }

    /***
     *
     * @param token 身份证
     * @param cookie
     * @param cursor 游标 查询返回的内容
     */
    @Override
    protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
        super.onQueryComplete(token, cookie, cursor);

        if (cursor != null && cursor.getCount() > 0){
            //cursor 开始的时候在-1 需要将其移动到第一个下标
            if (cursor.moveToFirst()){
                /**
                 *  从源码中可以看出调用此方法后会把当前的mCursor置为新传过来的cursor把原来的cursor返回去并关掉
                    作用:当我们的Cursor变化时调用此方法
                    adapter.changeCursor(cursor),它的功能类似于adapter.notifyDataSetChanged()方法
                 */
                myAdapter.changeCursor(cursor);
            }
        }else{
            Toast.makeText(MainActivity.this,R.string.cursor_null,Toast.LENGTH_SHORT).show();
        }

    }
}

MyAdaper:

/**
 * Created by XX on 2018/4/30.
 */

class MyAdapter extends CursorAdapter {
    private Context mContext;
    private  LayoutInflater layoutInflater;

    /**
     *
     * @param context 上下文
     * @param c 游标 cursor
     * @param autoRequery true时 数据库更新将自动刷新listView
     */
    public MyAdapter(Context context, Cursor c, boolean autoRequery) {
        super(context, c, autoRequery);
        this.mContext = context;
        this.layoutInflater = LayoutInflater.from(mContext);
    }

    public MyAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
        this.mContext = context;
        this.layoutInflater = LayoutInflater.from(mContext);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {

        View view = layoutInflater.inflate(R.layout.test_item, parent, false);
        return view;
    }

    /***
     *  instanceof: java里面的二元运算符,
     * 判断左边的对象是否是右边类的实例。假如是的话,返回true;假如不是的话,返回false。
     */
    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ConversationItem conversationItem = null;
        if (view instanceof ConversationItem){
            conversationItem = (ConversationItem) view;
        }

        if (conversationItem != null){
            ConversationBean conversationBean = new ConversationBean(cursor);
            conversationItem.bindValues(conversationBean);
        }
    }
}

ConversationItem:

/**
 * Created by Chauncy_Tan on 2018/5/10.
 *
 * ConversationItem 继承了LinearLayout 没错我们的list item整个布局的最外层就是一个LinearLayout
 * 为了更好地赋值我们将使用我们这个自定义的LinearLayout
 */



public class ConversationItem extends LinearLayout {

    private TextView mContent;

    public ConversationItem(Context context) {
        super(context);
    }

    public ConversationItem(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public ConversationItem(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mContent = findViewById(R.id.txt_content);
    }
    //用于绑定为控件赋值
    public void bindValues(ConversationBean conversationBean){
        mContent.setText(conversationBean.getmContent());
    }
}

ConversationBean:

/**
 * Created by XX on 2018/5/10.
 */

public class ConversationBean {
    public ConversationBean(Cursor cursor) {
        if (cursor != null){
            String snippet = cursor.getString(cursor.getColumnIndex(Telephony.Threads.SNIPPET));
            setmContent(snippet);
        }
    }
    private String mContent;

    public String getmContent() {
        return mContent;
    }

    public void setmContent(String mContent) {
        this.mContent = mContent;
    }
}

ListView的每一个Item布局文件:

<com.example.test.ConversationItem
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="56dp">

    <TextView
        android:id="@+id/txt_content"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:gravity="center"
        android:lines="1"
        android:text="TextView" />

   
</com.example.test.ConversationItem>

AsyncQueryHandler内部实现

AsyncQueryHandler类封装了调用者线程与工作线程的交互过程。交互的主体是两个Handler,一个运行在调用者线程中,一个运行在工作者线程中。通过提供onXXXComplete的回调接口,实现事件的完成处理。


刚刚接触query()以及startQuery()时对它的参数我是一脸懵逼,其实这些参数是能够拼接成一个完整的SQL语句

startQuery()

token:就好比人的身份证,startQuery()可以多次调用返回多个结果,用token来区分

cookie:你想传给onXXXComplete方法使用的一个对象。(暂时我还没用到一直是null)

uri:你可以理解为从哪一个表查(from xxxtable)

projection:你查询需要返回的字段,null代表 * 

selection:你的查询条件

selectionArgs:查询参数

orderBy:排序条件

@param token A token passed into {@link #onQueryComplete} to identify
*  the query.
* @param cookie An object that gets passed into {@link #onQueryComplete}
* @param uri The URI, using the content:// scheme, for the content to
*         retrieve.
* @param projection A list of which columns to return. Passing null will
*         return all columns, which is discouraged to prevent reading data
*         from storage that isn't going to be used.
* @param selection A filter declaring which rows to return, formatted as an
*         SQL WHERE clause (excluding the WHERE itself). Passing null will
*         return all rows for the given URI.
* @param selectionArgs You may include ?s in selection, which will be
*         replaced by the values from selectionArgs, in the order that they
*         appear in the selection. The values will be bound as Strings.
* @param orderBy How to order the rows, formatted as an SQL ORDER BY
*         clause (excluding the ORDER BY itself). Passing null will use the
*         default sort order, which may be unordered.

query()

query没有token以及Cookie参数没有token因为它是同步的,cookie我还在了解

@param uri The URI, using the content:// scheme, for the content to
*         retrieve.
* @param projection A list of which columns to return. Passing null will
*         return all columns, which is inefficient.
* @param selection A filter declaring which rows to return, formatted as an
*         SQL WHERE clause (excluding the WHERE itself). Passing null will
*         return all rows for the given URI.
* @param selectionArgs You may include ?s in selection, which will be
*         replaced by the values from selectionArgs, in the order that they
*         appear in the selection. The values will be bound as Strings.
* @param sortOrder How to order the rows, formatted as an SQL ORDER BY
*         clause (excluding the ORDER BY itself). Passing null will use the
*         default sort order, which may be unordered.




猜你喜欢

转载自blog.csdn.net/qq_37707251/article/details/80269439
今日推荐