Android ContentProvider结合数据库实现菜品的增删改查

ContentProvider提供一个接口,暴露自身的数据,其他应用就可以通过这个接口来实现源数据的增删改查。接下来我们就用一个小案例来演示一下
因为要用到Android的的四大组件之一ContentProvider,所以这里的数据提供者是menudemo
链接:https://pan.baidu.com/s/1i9mdcGIwsDch2MIh-hUTLw
提取码:0ytr
因为上传不了,所以只能给百度云的链接
下载好了之后,打开新的一个工程,File->New->Import Module,把解压好的menudemo导入
在这里插入图片描述
运行Menudemo,运行成功的界面的这样的
在这里插入图片描述
运行的过程中可能会报错,因为这个demo的环境问题跟你电脑上as的版本什么的有冲突,我是把menudemo里的build.gradle改了
在这里插入图片描述
把这个文件的内容改成如下:

apply plugin: 'com.android.application'

buildscript{
    repositories{
        jcenter()
    }

    dependencies{
        classpath "com.android.tools.build:gradle:2.3.3"
    }
}
android {
    compileSdkVersion 28
    buildToolsVersion "28.0.3"

    defaultConfig {
        applicationId "com.example.menudemo"
        minSdkVersion 15
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    implementation 'com.android.support:appcompat-v7:24.2.0'
    implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta1'
    testImplementation 'junit:junit:4.12'
}

具体的话要根据自己电脑的上AS的报错内容来改,不难的
之后就在新的工程里写代码了
这个Demo涉及到菜的名字以及类别,所以我们编写两个实体类
Dishlist.java

package com.example.myapplication.List;

public class DishList {
    public final static String DISH_ID="dish_id";//数据库里面的列名
    public final static String DISH_NAME="dish_name";//数据库里面的列名
    public final static String DISH_TYPE="dish_type";//数据库里面的列名
    private int id;
    private String name;
    private String type;

    public DishList() { }

    public DishList(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "DishList{" + "id=" + id + ", name='" + name + '\'' + ", type='" + type + '\'' + '}';
    }
}

TypeList.java

package com.example.myapplication.List;

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

public class TypeList {
    public final static String TYPE_ID = "type_id";//数据库里面的列名
    public final static String TYPE_NAME = "type_name";//数据库里面的列名
    private int id;
    private String typename;
    private List<DishList> children = new ArrayList<> ();
    //无参构造
    public TypeList(){}
    //双参构造
    public TypeList(int id, String typename) {
        this.id = id;
        this.typename = typename;
    }
    //添加子item的方法1
    public void addChild(DishList dishList){
        dishList.setType (getTypename ());
        children.add (dishList);
    }
    //添加子item的方法2
    public void addChild(int Childid,String Childname){
        DishList child = new DishList (Childid,Childname);
        child.setType (getTypename ());
        children.add (child);
    }

    public int getId() {
        return id;
    }

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

    public String getTypename() {
        return typename;
    }

    public void setTypename(String typename) {
        this.typename = typename;
    }

    public List<DishList> getChildren() {
        return children;
    }

    public void setChildren(List<DishList> children) {
        this.children = children;
    }
}

然后呢就是编写一下ExpandableListView的布局
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:orientation="vertical"
    tools:context=".MainActivity">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="56dp"
    android:background="#436EEE">
   <TextView
       android:id="@+id/add_tv"
       android:text="Add"
       android:textSize="25dp"
       android:textColor="#ffffff"
       android:layout_gravity="center_vertical"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginLeft="350dp"/>
</LinearLayout>
    <ExpandableListView
        android:id="@+id/id_expandable_lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    </ExpandableListView>


</LinearLayout>

父类的Item,也就是菜品的类型
activity_parent_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="56dp"
    android:orientation="horizontal"
    android:gravity="center_vertical">

    <TextView
        android:id="@+id/id_parent_item_tv"
        android:layout_width="match_parent"
        android:layout_height="56dp"
        android:layout_marginLeft="40dp"
        android:gravity="center_vertical"
        android:text="xxx"
        android:layout_gravity="center_vertical"
        android:textSize="20dp"
        android:textStyle="bold"/>

</LinearLayout>

子类的Item
activity_child_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"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical">
    <TextView
        android:id="@+id/id_child_item_tv"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:layout_marginStart="20dp"
        android:gravity="center_vertical"
        android:textSize="16dp"
        android:textStyle="bold"
        tools:text="我是子item" />

</LinearLayout>

然后我们写一个Dao类,获取数据
loadDataDao

package com.example.myapplication.Dao;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;

import com.example.myapplication.List.DishList;
import com.example.myapplication.List.TypeList;

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

//从Dao这里获取数据
public class loadDataDao {
    private static final String AUTHORITY = "com.imooc.menuprovider1";
    private static final String TABLE_A = "type_tb";//菜品类型表
    private static final String TABLE_B = "dish_tb";//菜品表
    public static final Uri CONTENT_URI_A = Uri.parse("content://" + AUTHORITY + "/" + TABLE_A);
    public static final Uri CONTENT_URI_B = Uri.parse("content://" + AUTHORITY + "/" + TABLE_B);
    public loadDataDao(){}
    //从ContentProvider中获取数据
    public List<TypeList> loadDatas(ContentResolver resolver){
        //将拿到的数据放回mDatas这里
        List<TypeList> mDatas = new ArrayList<> ();
        //查询菜品类型表
        Cursor c = resolver.query (CONTENT_URI_A,null,null,null,null);
        TypeList parent = null;
        while (c.moveToNext ()) {
            //拿到父类的Item
            parent = new TypeList ();
            int id = c.getInt (c.getColumnIndex (TypeList.TYPE_ID));
            String Typename = c.getString (c.getColumnIndex (TypeList.TYPE_NAME));
            parent.setId (id);
            parent.setTypename (Typename);
            mDatas.add (parent);
        }
        c.close ();
        DishList child = null;
        for (TypeList typeList : mDatas){
            String pTypename = typeList.getTypename ();
            Cursor c1 = resolver.query (CONTENT_URI_B,
                    null,
                    DishList.DISH_TYPE,//指定查询条件为父类的类名,
                    new String[]{pTypename},//指定条件值数组为typename
                    null);
            while (c1.moveToNext ()){
                child = new DishList ();
                int cid = c1.getInt (c1.getColumnIndex (DishList.DISH_ID));
                String cname = c1.getString (c1.getColumnIndex (DishList.DISH_NAME));
                child.setId (cid);
                child.setName (cname);
                child.setType (pTypename);
                typeList.addChild (child);
            }
            c1.close ();
        }
        return mDatas;
    }
}

之后写一个适配器将数据显示到ExpandableListView上
MenuAdapter.java

package com.example.myapplication.Adapter;

import android.app.AlertDialog;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.net.Uri;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;
import android.widget.TextView;
import android.widget.Toast;

import com.example.myapplication.List.DishList;
import com.example.myapplication.List.TypeList;
import com.example.myapplication.MainActivity;
import com.example.myapplication.R;
import java.util.List;

import static android.provider.ContactsContract.SyncState.CONTENT_URI;

public class MenuAdapter extends BaseExpandableListAdapter {

    private static final String AUTHORITY = "com.imooc.menuprovider1";
    private static final String TABLE_A = "type_tb";//菜品类型表
    private static final String TABLE_B = "dish_tb";//菜品表
    public static final Uri CONTENT_URI_A = Uri.parse ("content://" + AUTHORITY + "/" + TABLE_A);
    public static final Uri CONTENT_URI_B = Uri.parse ("content://" + AUTHORITY + "/" + TABLE_B);
    private Context context;
    private List<TypeList> mDatas;//显示的数据集
    private LayoutInflater mInflater;
    private ContentResolver resolver;

    public MenuAdapter(Context mContext, List<TypeList> mDatas, CallBack callBack) {
        this.context = mContext;
        this.mInflater = LayoutInflater.from (context);
        this.mDatas = mDatas;
        resolver = context.getContentResolver ();
    }

    public interface CallBack {
        void DeleteSuccess(List<TypeList> mDatas);
    }

    @Override
    public int getGroupCount() {
        return mDatas.size ();
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return mDatas.get (groupPosition).getChildren ().size ();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return mDatas.get (groupPosition);
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return mDatas.get (groupPosition).getChildren ().get (childPosition);
    }

    @Override
    public long getGroupId(int groupPosition) {
        return groupPosition;
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return childPosition;
    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded, View convertView, ViewGroup parent) {
    //数据缓存
        ParentViewHolder parentViewHolder;
        if (convertView == null) {
            parentViewHolder = new ParentViewHolder ();
            convertView = mInflater.inflate (R.layout.activity_parent_item, parent, false);
            //获取到控件
            parentViewHolder.p_tv = convertView.findViewById (R.id.id_parent_item_tv);
            convertView.setTag (parentViewHolder);
        } else {
            parentViewHolder = (ParentViewHolder) convertView.getTag ();
        }
        parentViewHolder.p_tv.setText (mDatas.get (groupPosition).getTypename ());
        return convertView;
    }

    @Override
    public View getChildView(final int groupPosition, final int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {
        ChildViewHolder childViewHolder;
        if (convertView == null) {
            childViewHolder = new ChildViewHolder ();
            convertView = mInflater.inflate (R.layout.activity_child_item, parent, false);
            childViewHolder.c_tv = convertView.findViewById (R.id.id_child_item_tv);
            convertView.setTag (childViewHolder);
        } else {
            childViewHolder = (ChildViewHolder) convertView.getTag ();
        }
        childViewHolder.c_tv.setText (mDatas.get (groupPosition).getChildren ().get (childPosition).getName ());
        //子Item的长按事件
        convertView.setOnLongClickListener (new View.OnLongClickListener () {
            @Override
            public boolean onLongClick(View v) {
                AlertDialog.Builder builder = new AlertDialog.Builder (context);
                builder.setTitle ("提示!!!");
                builder.setMessage ("你确定要删除嘛?");
                builder.setNegativeButton ("取消", new DialogInterface.OnClickListener () {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss ();
                    }
                });
                builder.setPositiveButton ("确定", new DialogInterface.OnClickListener () {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        resolver.delete (Uri.parse ("content://com.imooc.menuprovider1"), DishList.DISH_ID, new String[]{mDatas.get (groupPosition).getChildren ().
                                get (childPosition).getId () + ""});
                        mDatas.get (groupPosition).getChildren ().remove (childPosition);
                    }
                });
                builder.create ().show ();
                return true;
            }
        });
        convertView.setOnClickListener (new View.OnClickListener () {
            @Override
            public void onClick(View v) {
                Log.e ("TAG", "子item的点击事件");
                Log.e ("TAG", "子item的id是:" + mDatas.get (groupPosition).getChildren ().get (childPosition).getId ());
            }
        });
        return convertView;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

    //优化性能
    private static class ParentViewHolder {
        TextView p_tv;
    }

    private static class ChildViewHolder {
        TextView c_tv;
    }
}

之后我们要写一个布局来增加菜品
activity_add_data.xml

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:orientation="vertical"
    tools:context=".AddDishAcitivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="10dp"
            android:text="类型" />

        <Spinner
            android:id="@+id/add_data_sp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="10dp" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="10dp"
            android:text="菜名" />

        <EditText
            android:id="@+id/add_data_et"
            android:hint="请输入菜名"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginRight="15dp"
            android:layout_marginLeft="15dp"
            android:layout_marginTop="10dp" />

    </LinearLayout>
    <Button
        android:id="@+id/add_data_btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="确定"/>

</LinearLayout>

编写与之对应的类
AddDishActivity.java

package com.example.myapplication;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import com.example.myapplication.List.DishList;

public class AddDishActivity extends AppCompatActivity {

    private static final String AUTHORITY = "com.imooc.menuprovider1";
    public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY);
    private Spinner spinner;
    private EditText add_et;
    private Button add_btn;
    private ContentResolver resolver;
    private String dish_type;
    private String dish_name;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_data);
        //默认键盘不弹出
        getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
        initView();
        onListener();
        String[] arr = getResources ().getStringArray (R.array.type_name_string_arr);
        ArrayAdapter<String> mSpinnerAdapter = new ArrayAdapter<String> (AddDishAcitivity.this,
                android.R.layout.simple_spinner_item,arr);
        spinner.setAdapter (mSpinnerAdapter);
    }

    private void onListener() {
        spinner.setOnItemSelectedListener (new AdapterView.OnItemSelectedListener () {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                String[] arr = getResources ().getStringArray (R.array.type_name_string_arr);
                dish_type = arr[position];
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });
        add_btn.setOnClickListener (new View.OnClickListener () {
            @Override
            public void onClick(View v) {
                dish_name = add_et.getText ().toString ();
                ContentValues values = new ContentValues ();
                values.put(DishList.DISH_NAME, dish_name);
                values.put(DishList.DISH_TYPE, dish_type);
                Uri uri = resolver.insert(CONTENT_URI, values);
                long id = ContentUris.parseId (uri);
                Toast.makeText (AddDishAcitivity.this,"添加成功"+id,Toast.LENGTH_SHORT).show ();
                startActivity (new Intent (AddDishAcitivity.this,MainActivity.class));
                finish ();
            }
        });
    }

    private void initView() {
        spinner = findViewById(R.id.add_data_sp);
        add_et = findViewById(R.id.add_data_et);
        add_btn = findViewById(R.id.add_data_btn);
        resolver = getContentResolver();
    }
}

别忘了要在AndroidMainfest上进行注册
还有申请对应的权限

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_CONTACTS"/>
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/>

最后就是主函数

package com.example.myapplication;


import android.Manifest;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ExpandableListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.example.myapplication.Adapter.MenuAdapter;
import com.example.myapplication.Dao.loadDataDao;
import com.example.myapplication.List.TypeList;

import java.util.List;

public class MainActivity extends AppCompatActivity {
    private ExpandableListView ex_lv;
    private MenuAdapter mAdapter;
    private List<TypeList> mDatas;
    private TextView addTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView (R.layout.activity_main);
        int permission = ContextCompat.checkSelfPermission (this, Manifest.permission.READ_CONTACTS);
        if(permission != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions (this,new String[]{
                    Manifest.permission.READ_CONTACTS},1);
        }
        int permission1 = ContextCompat.checkSelfPermission (this, Manifest.permission.WRITE_CONTACTS);
        if(permission1 != PackageManager.PERMISSION_GRANTED){
            ActivityCompat.requestPermissions (this,new String[]{
                    Manifest.permission.WRITE_CONTACTS},2);
        }
        ex_lv = findViewById (R.id.id_expandable_lv);
        addTv = findViewById (R.id.add_tv);
        addTv.setOnClickListener (new View.OnClickListener () {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent (MainActivity.this,AddDishAcitivity.class);
                startActivity (intent);
            }
        });
        //1.拿到ContentProvider数据
        ContentResolver contentResolver = getContentResolver ();
        mDatas = new loadDataDao ().loadDatas (contentResolver);
        //2.获取适配器对象
        mAdapter = new MenuAdapter (this,mDatas,new MenuAdapter.CallBack (){
            public void DeleteSuccess(List<TypeList> mDatas){
                mAdapter.notifyDataSetChanged ();
            }
        });
        //将数据显示到ExpandableListView上
        ex_lv.setAdapter (mAdapter);
    }
}

之后就可以运行在模拟器了
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果有小伙伴需要这个Demo的话可以留言啦

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值