Android使用之CursorAdapter

CursorAdapter使用说明

  • CursorAdapter使用说明
    • 运用场景
    • CursorAdapter具体实现步骤
      • 实现步骤
        • 1 Item显示样式
          • 代码
          • XML结果
        • 2 创建Class
          • 构造方法
          • 代码
        • 3 在Class中继承CurosrAdapter
          • 重写子方法
          • 代码
        • 4 Activity对应的显示控件
          • 显示控件
          • 代码
          • XML结果
        • 5 在Activity中实现LoaderManagerLoaderCallbacks
          • 代码
        • 6 在Activity中载入Adapter
          • 相应控件载入Adapter
          • 代码

运用场景

主要用于在ListView或者GridView等中动态显示数据库中创建的数据,功能与AdapterView相似。

CursorAdapter具体实现步骤

实现步骤

  1. 创建XML文件用于将来Item显示样式
  2. 新建Class创建其相应的构造函数
  3. 继承CursorAdapter并重写相应的子方法
  4. 创建对应Activity的XML文件实现相应的显示控件
  5. 在Activity中实现LoaderManager.LoaderCallbacks获得该Content中的Cursor,用于将来Adapter的数据读取
  6. 在Activity中的相应控件中载入Adapter

1.1 Item显示样式

在Layout文件夹下创建一个XML文件用于实现将来在ListView中的Item需要显示的样式。这些并定义将来需要更改数据的id。

代码

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal">
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="10"
        android:orientation="vertical">
        
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:id="@+id/the_first_line">
            
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:id="@+id/display_number"
                android:layout_weight="1">
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="编号:" />
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:id="@+id/number_text_view"
                    android:text="223" />
            LinearLayout>
            
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:id="@+id/display_weight"
                android:layout_toRightOf="@+id/display_number"
                android:layout_weight="1">
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="体重:"
                    />
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="20"
                    android:id="@+id/weight_text_view"/>
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="Kg" />
            LinearLayout>
        LinearLayout>
        
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:id="@+id/the_second_line">
            
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:id="@+id/display_breed"
                android:layout_weight="1">
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="品种:" />
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:id="@+id/breed_text_view"
                    android:text="家猪" />
            LinearLayout>
            
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:id="@+id/display_eat_times"
                android:layout_weight="1">
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="吃食次数:" />
                <TextView
                    style="@style/DisplayItemBriefText"
                    android:text="2"
                    android:id="@+id/eat_times_text_view"/>
            LinearLayout>
        LinearLayout>
    LinearLayout>
    <ImageView
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:src="@drawable/ic_keyboard_arrow_right_black_48dp"
        android:layout_gravity="center"/>
LinearLayout>
XML结果

1.2 创建Class

构造方法

public BriefInformationAdapter(Context context, Cursor cursor)

创建该构造方法是为了将来在Activity中实现的时候能够将curosr中的数据传输进该Adapter,即其中的cursor就包含了需要的所有数据

代码
public class BriefInformationAdapter extends CursorAdapter {

    /**
     * 构造函数{@link BriefInformationAdapter}
     * @param context   显示的环境
     * @param cursor    显示的数据
     */
    public BriefInformationAdapter(Context context, Cursor cursor){
        super(context,cursor,0/*flag*/);
    }
  }

1.3 在Class中继承CurosrAdapter

重写子方法

继承CurosrAdapter后需要重写两个方法,分别是:
- public View newView(Context context, Cursor cursor, ViewGroup parent)
- public void bindView(View view, Context context, Cursor cursor)

newView方法用于实现创建新的View,将前文创建的Item样式在这里扩展显示。

bindView方法用于实现在新创建的View中将数据库中对应的数据显示到对应的id控件上。

代码
/**
 *用于适配显示在{@link EditPetInformationActivity}中的宠物的简略信息
 */
public class BriefInformationAdapter extends CursorAdapter {

    /**
     * 构造函数{@link BriefInformationAdapter}
     * @param context   显示的环境
     * @param cursor    显示的数据
     */
    public BriefInformationAdapter(Context context, Cursor cursor){
        super(context,cursor,0/*flag*/);
    }

    /**
     * 创建一个新的View用于显示
     * @param context   显示环境
     * @param cursor    从中获取显示的数据
     * @param parent    新的View是依附在那个环境中
     * @return 返回新的listView
     */
    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        /**膨胀显示的item的样式display_item**/
        return LayoutInflater.from(context).inflate(R.layout.display_item,parent,false);
    }

    /**
     * 用于将cursor中的数据匹配到相对应的标签中
     * @param view      newView方法中创建的view
     * @param context   显示环境
     * @param cursor    从该cursor中提取数据
     */
    @Override
    public void bindView(View view, Context context, Cursor cursor) {

        /**
         * 确定需要显示的TextView
         */
        TextView numberTextView=(TextView) view.findViewById(R.id.number_text_view);
        TextView breedTextView=(TextView) view.findViewById(R.id.breed_text_view);
        TextView weightTextView=(TextView) view.findViewById(R.id.weight_text_view);
        TextView eatTimesTextView=(TextView) view.findViewById(R.id.eat_times_text_view);

        /**
         * 找到各个内容的列标签
         */
        int numberColumnIndex=cursor.getColumnIndex(PetInforamtionDatabase.COLUMN_PET_INIT_NUMBER);
        int breedColumnIndex=cursor.getColumnIndex(PetInforamtionDatabase.COLUMN_PET_BRRED);
        int weightColumnIndex=cursor.getColumnIndex(PetInforamtionDatabase.COLUMN_PET_WEIGHT);
        int eatTimesColumnIndex=cursor.getColumnIndex(PetInforamtionDatabase.COLUMN_PET_EAT_TIMES);

        /**
         *读取对应标签的信息
         */
        int number=cursor.getInt(numberColumnIndex);
        String breed=cursor.getString(breedColumnIndex);
        int weight=cursor.getInt(weightColumnIndex);
        int eatTimes=cursor.getInt(eatTimesColumnIndex);

        /**
         * 设置显示Cursor中读取的内容
         */
        numberTextView.setText(String.valueOf(number));
        breedTextView.setText(breed);
        weightTextView.setText(String.valueOf(weight));
        eatTimesTextView.setText(String.valueOf(eatTimes));

    }

}

1.4 Activity对应的显示控件

显示控件

这里采用的是ListView用于显示。

代码

<RelativeLayout
    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="match_parent"
    tools:context="com.android.kimhlo.smartfeed.ui.EditPetInformationActivity">
    <ListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/brief_information_list_view">
    ListView>

    
    <RelativeLayout
        android:id="@+id/brief_empty_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/empty_information"
            android:gravity="center"
            android:text="没有宠物信息,请加入宠物。"
            android:textSize="20sp"
            android:textColor="#A2AAB0"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/empty_information"
            android:text="点击右下角的浮动按钮添加"
            android:textSize="20sp"
            android:textColor="#A2AAB0"/>
    RelativeLayout>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/add_Pet_floating_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        app:srcCompat="@drawable/ic_add_white_24dp"
        android:layout_alignParentBottom="true"
        android:layout_alignParentEnd="true"
        android:layout_marginEnd="30dp"
        android:layout_marginBottom="30dp"/>
RelativeLayout>
XML结果

1.5 在Activity中实现LoaderManager.LoaderCallbacks

实现该接口主要为了获得在content下对应projection的cursor,用于Adapter的创建。采用Loader的原因在于不必每次旋转屏幕的时候重新执行onCreate的时候都重新创建新的Curosr从而防止内存泄露等各种问题。

实现该接口就必须要实现三个子方法:

  • public Loader onCreateLoader(int id, Bundle args)
  • public void onLoadFinished(Loader loader, Cursor data)
  • public void onLoaderReset(Loader loader)

其中,onCreateLoader方法用于检测是否需要创建新的Loader,即不会每次都去创建新的curosr。onLoadFinished方法是当创建完成后的操作,有数据更改后用新的Cursor去更新BriefInformationAdapter。onLoaderReset是Loader重置后的操作,当数据需要被删除的时候回调该函数。

在onCreate函数中通过getLoaderManager().initLoader(PET_LOADER,null,this)来初始化Loader,PET_LOADER是该Loader的标号。(实现在1.6中代码部分见)

代码
//创建Loader
@Override
public Loader onCreateLoader(int id, Bundle args) {

    //在cursor中需要显示的信息
    String[] projection ={
            PetInforamtionDatabase._ID,
            PetInforamtionDatabase.COLUMN_PET_INIT_NUMBER,
            PetInforamtionDatabase.COLUMN_PET_WEIGHT,
            PetInforamtionDatabase.COLUMN_PET_HEAD_TEMPERATURE,
            PetInforamtionDatabase.COLUMN_PET_BODY_TEMPERATURE,
            PetInforamtionDatabase.COLUMN_PET_EAT_TIMES,
            PetInforamtionDatabase.COLUMN_PET_BRRED
    };

    //Loader将会在后台执行ContentProvider的query方法
    return new CursorLoader(
            this,//显示该信息的环境就是该Activity
            PetInforamtionDatabase.CONTENT_URI,//查询的地址
            projection,//查询的信息内容
            null,//没有选择的条件
            null,//没有选择的条件值
            null//默认的方式排序
    );
}

//载入Loader完成后
@Override
public void onLoadFinished(Loader loader, Cursor data) {
    //用新的Cursor去更新{@link BriefInformationAdapter}
    mCursorAdapter.swapCursor(data);
}

@Override
public void onLoaderReset(Loader loader) {
    //当数据需要被删除的时候回掉
    mCursorAdapter.swapCursor(null);
}

1.6 在Activity中载入Adapter

相应控件载入Adapter

在对应的Activity中的onCreate函数中确定相应的显示控件,这里采用的是该Activity的XML中对应的ListView控件。找到相应的控件后用setAadapter方法设置实例化后的Adapter就可以完成显示

代码
public class EditPetInformationActivity extends AppCompatActivity
        implements LoaderManager.LoaderCallbacks<Cursor>{

    /**该Activity的Loader的编号**/
    private static final int PET_LOADER=0;

    /**ListView对应的适配器**/
    BriefInformationAdapter mCursorAdapter;


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

        //设置浮动按钮的触发Activity
        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.add_Pet_floating_button);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent addPet=new Intent(EditPetInformationActivity.this,AddPetActivity.class);
                startActivity(addPet);
            }
        });

        //确定显示用来显示宠物详细信息的ListView
        ListView briefInformationListView=(ListView) findViewById(R.id.brief_information_list_view);

        View emptyView=findViewById(R.id.brief_empty_view);
        briefInformationListView.setEmptyView(emptyView);

        //设置Adapter
        mCursorAdapter=new BriefInformationAdapter(this,null);
        briefInformationListView.setAdapter(mCursorAdapter);

        //设置ListView的元素点击事件
        briefInformationListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView parent, View view, int position, long id) {
                //设置相应的Intent打开对应的Activity
                Intent openDetail=new Intent(EditPetInformationActivity.this,ItemDetailInformationActivity.class);
                //通过id去创建相应的Uri
                Uri mCurrentUri= ContentUris.withAppendedId(PetInforamtionDatabase.CONTENT_URI,id);
                //发送生成的Uri到Intent
                openDetail.setData(mCurrentUri);
                //打开相应的Activity
                startActivity(openDetail);
            }
        });

        getLoaderManager().initLoader(PET_LOADER,null,this);
    }

你可能感兴趣的:(android)