ContentProvider学习笔记

       在学习鸿洋的 幕课网 节日短信送祝福的视频( 观看地址:http://www.imooc.com/view/517 )的时候,遇到一个知识点ContentProvider的使用。以前只是知道其作用,但是重来没有用过,正好借这个机会,好好学习一下。下面把学习笔记记录下来:

       ContentProvider:为存储和获取数据提供统一的接口。可以在不同的应用程序之间共享数据。Android已经为常见的一些数据提供了默认的ContentProvider,最常用的就是通讯录的对处接口。

       我们平时常用的都是调用官居方提供的,很少使用自己的,这回借着学习这个视频,正好自己做一个试一下。

      功能说明:

               自己做一个简单的发送短信的功能,当然了,并没有真的加发短信的代码,只是存入数据库中,各位要想真的发短信,可以查看上面的观看地址里面有,代码也很简单,几行代码,只是我使用的是模拟机,一是无法真发,二是这个例子主要是ContentProvider,所以就是直接入库了,废话说了这么多。进入正题

               此学习笔记的例子,是两个程序,一个是简单的模拟发送短信,信息入库,并建立ContentProvider,另一个是采用Loader的方法接收信息,时时显示数据。

              开发工具是android studio  

              好了不多说了,直接上代码,我在代码里的注解比较清楚了,就不多说了,

            短信发送程序contentproviderlearn

           首先,我们要先为我们的的数据库建立对应的model类,并在其中定义表名与字段名

           SMS_send.java

          

package com.example.cg.contentproviderlearn.models;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 信息基础类
 * Created by cg on 2015/11/7.
 */
public class SMS_send {
    private int id;                           //信息id,标识种子
    private String msg_content;               //信息内容
    private String number;                    //收信人的手机号
    private String name;                      //收信人的名字
    private String festivalName;              //节日名称
    private Date date;                        //发短信日期
    private String dateStr;
    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    /**
     * 定义生成的数据库表名,与字段名,为了方便调用
     */
    public static final String TABLE_NAME = "tb_sended_msg";
    public static final String COLUMN_MSG = "msg_content";
    public static final String COLUMN_NUMBER = "number";
    public static final String COLUMN_NAME = "name";
    public static final String COLUMN_FESTIVALName = "festivalName";
    public static final String COLUMN_DATE = "date";


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getMsg_content() {
        return msg_content;
    }

    public void setMsg_content(String msg_content) {
        this.msg_content = msg_content;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public String getFestivalName() {
        return festivalName;
    }

    public void setFestivalName(String festivalName) {
        this.festivalName = festivalName;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getDateStr() {
        dateStr = df.format(date);
        return dateStr;
    }
}

      再为数据库的操作编写一个类myDbHelper.java

package com.example.cg.contentproviderlearn.Db;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.example.cg.contentproviderlearn.models.SMS_send;

/**
 * 数据库操作
 * Created by cg on 2015/11/7.
 */
public class myDbHelper extends SQLiteOpenHelper {

    //定义数据库的名字
    private static String DBName = "sms.db";
    //定义数据库的版本号
    private static int VERSION = 1;

    //采用单例模式
    private static myDbHelper mDbHelper;

    public static myDbHelper getInstance(Context context)
    {
        if(mDbHelper==null)
        {
            synchronized (myDbHelper.class)
            {
                if(mDbHelper==null)
                {
                    mDbHelper = new myDbHelper(context);
                }
            }
        }

        return  mDbHelper;
    }

    private myDbHelper(Context context) {
        super(context, DBName, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        String sql = "create table " + SMS_send.TABLE_NAME + "(" +
                "_id integer primary key autoincrement," +
                SMS_send.COLUMN_DATE + " integer ," +
                SMS_send.COLUMN_FESTIVALName + " text," +
                SMS_send.COLUMN_MSG + " text," +
                SMS_send.COLUMN_NAME + " text," +
                SMS_send.COLUMN_NUMBER + " text" + ")";

        db.execSQL(sql);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

    好基础功能,做完了,我们来写ContentProvide的代码:

    myContentProvider.java

package com.example.cg.contentproviderlearn.Db;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;

import com.example.cg.contentproviderlearn.models.SMS_send;

/**
 * 定义的ContentProvider,功能主要用于添加和查询数据
 * Created by cg on 2015/11/7.
 */
public class myContentProvider extends ContentProvider {

    //定义对外的唯一的标识名
    public static final String AUTOHORITY = "com.example.cg.ContentProviderLearn.provider";
    //定义要操作数据的URI
    public static final Uri URI_SMS_ALL = Uri.parse("content://" + AUTOHORITY + "/sms");
    //定义用于操作Uri的工具类,用于匹配Uri
    private static UriMatcher matcher;
    //定义Uri路径的返回码,0:返回所有 1:返回单个
    private static final int SMS_ALL = 0;
    private static final int SMS_ONE = 1;

    //把需要匹配Uri路径全部给注册上
    static {
        //常量UriMatcher.NO_MATCH表示不匹配任何路径的返回码(-1)
        matcher = new UriMatcher(UriMatcher.NO_MATCH);
        //匹配所有
        matcher.addURI(AUTOHORITY,"sms",SMS_ALL);
        //匹配单个,#为通配符
        matcher.addURI(AUTOHORITY,"sms/#",SMS_ONE);
    }

    //定义操作数据库
    private myDbHelper mHelper;
    private SQLiteDatabase mDb;

    @Override
    public boolean onCreate() {
        mHelper = myDbHelper.getInstance(getContext());
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
        int match = matcher.match(uri);

        switch (match)
        {
            case SMS_ALL:
                break;
            case SMS_ONE:
                long id = ContentUris.parseId(uri);
                selection = "_id= ?";
                selectionArgs = new String[]{String.valueOf(id)};
                break;
            default:throw new IllegalArgumentException("Unknown URI :" + uri);
        }

        mDb = mHelper.getReadableDatabase();
        Cursor query = mDb.query(SMS_send.TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);

        //必须加上此句,用来通知数据接收方
        query.setNotificationUri(getContext().getContentResolver(),URI_SMS_ALL);

        return query;
    }

    @Override
    public String getType(Uri uri) {
        return null;
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        //先取得传入uri的匹配码,判断是否与返回全部的匹配码对应,如果不是,返回错误
        int match = matcher.match(uri);
        if(match!=SMS_ALL)
        {
            throw new IllegalArgumentException("Unknown URI :" + uri);
        }

        //如果传入uri正确,则开始写数据库,将数据设置为可写
        mDb = mHelper.getWritableDatabase();

        long insertRowID = mDb.insert(SMS_send.TABLE_NAME, null, values);

        if(insertRowID>0)
        {
            // 如果ContentProvider的访问者需要得知ContentProvider中的数据发生了变化,可以在
            // ContentProvider 发生数据变化时调用getContentResolver().notifyChange(uri, null)来
            // 通知注册在此URI上的访问者
            getContext().getContentResolver().notifyChange(URI_SMS_ALL, null);
            //withAppendedId(uri, id)用于为路径加上ID部分
            return ContentUris.withAppendedId(uri,insertRowID);
        }

        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        return 0;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        return 0;
    }
}

 我们把我们的 ContentProvide写完之后, 一定要记录,要去AndroidManifest.xml文件注册一下。

<provider
            android:authorities="com.example.cg.ContentProviderLearn.provider"
            android:name=".Db.myContentProvider" />

这里面authorities是你在ContentPRovide定义的,这个要注意,一定要定义为唯一的,就是你手机里,所有的程序,就只有这一个名字.

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="节日名称:"/>
        <EditText
            android:id="@+id/edit_festivalName"
            android:layout_width="0dp"
            android:layout_weight="3"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="节日祝词:"/>
    <EditText
        android:id="@+id/edit_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textMultiLine"
        android:lines="3"
        android:gravity="top|left"/>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="收件人:"/>
        <EditText
            android:id="@+id/edit_name"
            android:layout_width="0dp"
            android:layout_weight="3"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="电话号:"/>
        <EditText
            android:id="@+id/edit_phone"
            android:layout_width="0dp"
            android:layout_weight="3"
            android:layout_height="wrap_content" />
    </LinearLayout>
    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送"
        android:layout_margin="8dp"
        android:layout_gravity="right"/>

</LinearLayout>

MainActivity.java

package com.example.cg.contentproviderlearn;

import android.content.ContentValues;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import com.example.cg.contentproviderlearn.Db.myContentProvider;
import com.example.cg.contentproviderlearn.models.SMS_send;

import java.util.Date;

public class MainActivity extends AppCompatActivity {

    private EditText edit_festivalName;
    private EditText edit_content;
    private EditText edit_name;
    private EditText edit_phone;
    private Button btn_add;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initControls();
    }

    /**
     * 初始化各控件,并为按钮添加点击事件
     */
    private void initControls() {
        edit_festivalName = (EditText)findViewById(R.id.edit_festivalName);
        edit_content = (EditText)findViewById(R.id.edit_content);
        edit_name = (EditText)findViewById(R.id.edit_name);
        edit_phone = (EditText)findViewById(R.id.edit_phone);
        btn_add = (Button)findViewById(R.id.btn_add);
        btn_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                SMS_send smsSend = new SMS_send();

                smsSend.setDate(new Date());
                ContentValues values = new ContentValues();
                values.put(SMS_send.COLUMN_DATE,smsSend.getDate().getTime());
                values.put(SMS_send.COLUMN_FESTIVALName,edit_festivalName.getText().toString());
                values.put(SMS_send.COLUMN_MSG,edit_content.getText().toString());
                values.put(SMS_send.COLUMN_NAME,edit_name.getText().toString());
                values.put(SMS_send.COLUMN_NUMBER,edit_phone.getText().toString());

                getApplicationContext().getContentResolver().insert(myContentProvider.URI_SMS_ALL,values);
            }
        });
    }


}
界面如下图:

 下面,我们来看一下,接收的程序 loadingcontentproviderlearn

 这个里面,也是先要建立一个数据的models类,它与上面的程序中是一样的。

 SMS_send.java

package com.example.cg.loadingcontentproviderlearn.models;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by cg on 2015/11/5.
 */
public class SMS_send {

    private int id;
    private String msg_content;
    private String number;
    private String name;
    private String festivalName;
    private Date date;
    private String dateStr;
    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");

    public static final String TABLE_NAME = "tb_sended_msg";
    public static final String COLUMN_MSG = "msg_content";
    public static final String COLUMN_NUMBER = "number";
    public static final String COLUMN_NAME = "name";
    public static final String COLUMN_FESTIVALName = "festivalName";
    public static final String COLUMN_DATE = "date";


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getMsg_content() {
        return msg_content;
    }

    public void setMsg_content(String msg_content) {
        this.msg_content = msg_content;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public String getName() {
        return name;
    }

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

    public String getFestivalName() {
        return festivalName;
    }

    public void setFestivalName(String festivalName) {
        this.festivalName = festivalName;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getDateStr() {
        dateStr = df.format(date);
        return dateStr;
    }

}

我在显示收到短信的用户信息时,使用了鸿洋的FlowLayout,它的代码,如下,如果你想了解细节,就去幕课网上,找相应的视频

FlowLayout.java

package com.example.cg.loadingcontentproviderlearn.untils;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;

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

/**
 * Created by cg on 2015/11/2.
 */
public class FlowLayout extends ViewGroup {


    private static final String TAG = "FlowLayout";


    public FlowLayout(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    @Override
    protected LayoutParams generateLayoutParams(
            LayoutParams p)
    {
        return new MarginLayoutParams(p);
    }

    @Override
    public LayoutParams generateLayoutParams(AttributeSet attrs)
    {
        return new MarginLayoutParams(getContext(), attrs);
    }

    @Override
    protected LayoutParams generateDefaultLayoutParams()
    {
        return new MarginLayoutParams(LayoutParams.MATCH_PARENT,
                LayoutParams.MATCH_PARENT);
    }

    /**
     * 负责设置子控件的测量模式和大小 根据所有子控件设置自己的宽和高
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        // 获得它的父容器为它设置的测量模式和大小
        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);
        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);
        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);
        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

        Log.e(TAG, sizeWidth + "," + sizeHeight);

        // 如果是warp_content情况下,记录宽和高
        int width = 0;
        int height = 0;
        /**
         * 记录每一行的宽度,width不断取最大宽度
         */
        int lineWidth = 0;
        /**
         * 每一行的高度,累加至height
         */
        int lineHeight = 0;

        int cCount = getChildCount();

        // 遍历每个子元素
        for (int i = 0; i < cCount; i++)
        {
            View child = getChildAt(i);
            // 测量每一个child的宽和高
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            // 得到child的lp
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            // 当前子空间实际占据的宽度
            int childWidth = child.getMeasuredWidth() + lp.leftMargin
                    + lp.rightMargin;
            // 当前子空间实际占据的高度
            int childHeight = child.getMeasuredHeight() + lp.topMargin
                    + lp.bottomMargin;
            /**
             * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行
             */
            if (lineWidth + childWidth > sizeWidth - getPaddingLeft() - getPaddingRight())
            {
                width = Math.max(lineWidth, childWidth);// 取最大的
                lineWidth = childWidth; // 重新开启新行,开始记录
                // 叠加当前高度,
                height += lineHeight;
                // 开启记录下一行的高度
                lineHeight = childHeight;
            } else
            // 否则累加值lineWidth,lineHeight取最大高度
            {
                lineWidth += childWidth;
                lineHeight = Math.max(lineHeight, childHeight);
            }
            // 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较
            if (i == cCount - 1)
            {
                width = Math.max(width, lineWidth);
                height += lineHeight;
            }

        }
        setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth
                : width + getPaddingRight() + getPaddingLeft(), (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight
                : height + getPaddingTop() + getPaddingBottom());

    }
    /**
     * 存储所有的View,按行记录
     */
    private List<List<View>> mAllViews = new ArrayList<List<View>>();
    /**
     * 记录每一行的最大高度
     */
    private List<Integer> mLineHeight = new ArrayList<Integer>();
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b)
    {
        mAllViews.clear();
        mLineHeight.clear();

        int width = getWidth();

        int lineWidth = 0;
        int lineHeight = 0;
        // 存储每一行所有的childView
        List<View> lineViews = new ArrayList<View>();
        int cCount = getChildCount();
        // 遍历所有的孩子
        for (int i = 0; i < cCount; i++)
        {
            View child = getChildAt(i);
            MarginLayoutParams lp = (MarginLayoutParams) child
                    .getLayoutParams();
            int childWidth = child.getMeasuredWidth();
            int childHeight = child.getMeasuredHeight();

            // 如果已经需要换行
            if (childWidth + lp.leftMargin + lp.rightMargin + lineWidth > width - getPaddingLeft() - getPaddingLeft())
            {
                // 记录这一行所有的View以及最大高度
                mLineHeight.add(lineHeight);
                // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView
                mAllViews.add(lineViews);
                lineWidth = 0;// 重置行宽
                lineViews = new ArrayList<View>();
            }
            /**
             * 如果不需要换行,则累加
             */
            lineWidth += childWidth + lp.leftMargin + lp.rightMargin;
            lineHeight = Math.max(lineHeight, childHeight + lp.topMargin
                    + lp.bottomMargin);
            lineViews.add(child);
        }
        // 记录最后一行
        mLineHeight.add(lineHeight);
        mAllViews.add(lineViews);

        int left = getPaddingLeft();
        int top = getPaddingTop();
        // 得到总行数
        int lineNums = mAllViews.size();
        for (int i = 0; i < lineNums; i++)
        {
            // 每一行的所有的views
            lineViews = mAllViews.get(i);
            // 当前行的最大高度
            lineHeight = mLineHeight.get(i);

            Log.e(TAG, "第" + i + "行 :" + lineViews.size() + " , " + lineViews);
            Log.e(TAG, "第" + i + "行, :" + lineHeight);

            // 遍历当前行所有的View
            for (int j = 0; j < lineViews.size(); j++)
            {
                View child = lineViews.get(j);
                if (child.getVisibility() == View.GONE)
                {
                    continue;
                }
                MarginLayoutParams lp = (MarginLayoutParams) child
                        .getLayoutParams();

                //计算childView的left,top,right,bottom
                int lc = left + lp.leftMargin;
                int tc = top + lp.topMargin;
                int rc =lc + child.getMeasuredWidth();
                int bc = tc + child.getMeasuredHeight();

                Log.e(TAG, child + " , l = " + lc + " , t = " + t + " , r ="
                        + rc + " , b = " + bc);

                child.layout(lc, tc, rc, bc);

                left += child.getMeasuredWidth() + lp.rightMargin
                        + lp.leftMargin;
            }
            left = getPaddingLeft();
            top += lineHeight;
        }

    }
}

为了让显示出来的用户名,好看一点,我加了一个布局:

activity_send_msg_flow.xml

<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="#e3e3"
    android:layout_margin="4dp"
    android:background="@drawable/tag_bg"
    >

</TextView>

背景tag_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#ffffff"></solid>

    <stroke android:color="#e3e3" android:width="2dp"></stroke>
    <corners android:radius="8dp"></corners>
    <padding android:left="8dp" android:right="8dp" android:bottom="2dp" android:top="2dp"></padding>
</shape>

好,我们来看一下,主程序的布局:activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <ListView
        android:id="@+id/lv_sms"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />

</LinearLayout>

这个比较简单,就是设置一个listView,下面,我们把listView的布局,给出来:

fragment_sms_lv_item.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/txt_item_content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:padding="8dp"/>
    <com.example.cg.loadingcontentproviderlearn.untils.FlowLayout
        android:id="@+id/flow_item_username"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">
    </com.example.cg.loadingcontentproviderlearn.untils.FlowLayout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/txt_item_festivalName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/txt_item_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>

</LinearLayout>

为ListVIew编写Adapter布局smsAdapter.java

package com.example.cg.loadingcontentproviderlearn.Adapter;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.example.cg.loadingcontentproviderlearn.R;
import com.example.cg.loadingcontentproviderlearn.models.SMS_send;
import com.example.cg.loadingcontentproviderlearn.untils.FlowLayout;

import java.util.List;

/**
 * Created by cg on 2015/11/6.
 */
public class smsAdapter extends BaseAdapter {

    private List<SMS_send> list_sms;
    private LayoutInflater inflater;
    private Context context;

    public smsAdapter(Context context,List<SMS_send> list_sms) {
        this.inflater = LayoutInflater.from(context);
        this.list_sms = list_sms;
        this.context = context;
    }

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

    @Override
    public Object getItem(int position) {
        return list_sms.get(position);
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        smsInfo sInfo;
        if(convertView==null)
        {
            sInfo = new smsInfo();
            convertView = inflater.inflate(R.layout.fragment_sms_lv_item,parent,false);
            sInfo.content = (TextView)convertView.findViewById(R.id.txt_item_content);
            sInfo.date = (TextView)convertView.findViewById(R.id.txt_item_date);
            sInfo.festName = (TextView)convertView.findViewById(R.id.txt_item_festivalName);
            sInfo.flow = (FlowLayout)convertView.findViewById(R.id.flow_item_username);

            convertView.setTag(sInfo);
        }else{

            sInfo = (smsInfo)convertView.getTag();
        }

        sInfo.content.setText(list_sms.get(position).getMsg_content());
        sInfo.festName.setText(list_sms.get(position).getFestivalName());
        sInfo.date.setText("2015-11-07");

        sInfo.flow.removeAllViews();

        for(String name:list_sms.get(position).getName().split(",")) {

            TextView view = (TextView)inflater.inflate(R.layout.activity_send_msg_flow, sInfo.flow, false);
            view.setText(name);
            sInfo.flow.addView(view);
        }


        return convertView;
    }


    public class smsInfo
    {
        TextView content;
        FlowLayout flow;
        TextView festName;
        TextView date;
    }
}

好,这回我们来看一下,主程序:

mainActivity.java

package com.example.cg.loadingcontentproviderlearn;

import android.app.LoaderManager;
import android.content.CursorLoader;
import android.content.Loader;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;

import com.example.cg.loadingcontentproviderlearn.Adapter.smsAdapter;
import com.example.cg.loadingcontentproviderlearn.models.SMS_send;

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

public class MainActivity extends AppCompatActivity {

    private ListView lv_sms;
    private smsAdapter sAdapter;

    private List<SMS_send> list_sms;

    private static int LOAD_ID = 1;

    //定义对外的唯一的标识名
    private static final String AUTOHORITY = "com.example.cg.ContentProviderLearn.provider";
    //定义要操作数据的URI
    public static final Uri URI_SMS_ALL = Uri.parse("content://" + AUTOHORITY + "/sms");

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initControls();
    }

    /**
     * 初始化控件同,并为listView加载数据
     */
    private void initControls() {
        lv_sms = (ListView)findViewById(R.id.lv_sms);

        list_sms = new ArrayList<>();

        //采用Loader的方式加载
        getLoaderManager().initLoader(LOAD_ID, null, new LoaderManager.LoaderCallbacks<Cursor>() {
            @Override
            public Loader<Cursor> onCreateLoader(int id, Bundle args) {

                CursorLoader loader = new CursorLoader(MainActivity.this,URI_SMS_ALL,null,null,null,null);

                return loader;
            }

            @Override
            public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
                if(loader.getId()==LOAD_ID)
                {
                    list_sms.clear();
                    while(data.moveToNext())
                    {
                        SMS_send send = new SMS_send();
                        send.setNumber(data.getString(data.getColumnIndex(SMS_send.COLUMN_NUMBER)));
                        send.setName(data.getString(data.getColumnIndex(SMS_send.COLUMN_NAME)));
                        send.setMsg_content(data.getString(data.getColumnIndex(SMS_send.COLUMN_MSG)));
                        send.setFestivalName(data.getString(data.getColumnIndex(SMS_send.COLUMN_FESTIVALName)));

                        list_sms.add(send);
                    }

                    sAdapter = new smsAdapter(MainActivity.this,list_sms);
                    lv_sms.setAdapter(sAdapter);

                }
            }

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

            }
        });
    }


}

OK,这时,两个程序,就写完了。

这里要注意一点的是,第二个程序,我们虽然调用了第一个程序中的ContentProvider,可是千万不要在第二个程序里注册,否则就会报错。

你现在把这两个程序全打开,在第一个程序中添加一个记录,然后,你就会看到在第二个程序中,自动就有新数据刷新出来了,是不是很有意思

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值