文档章节

LiveData+ViewMode+Room初次使用

Magic_锋
 Magic_锋
发布于 2018/10/29 15:36
字数 1399
阅读 61
收藏 0

        LiveData是持有被观察数据的类,是有生命周期感知的,只有在STARTED和RESUME的状态下才可通知数据的变化, 他的优点就是

再也不用担心oom了

再也不用手动处理生命周期了

实时刷新数据

        ViewMode是存放和UI相关数据的,他最大优点就是再也不懂但是activity在屏幕旋转的时候数据被影响了,之前屏幕旋转的时候,我们要对onsaveinstance进行处理,来保证数据不会丢失,但是这只是对少量数据有效,但是使用ViewMode后,妈妈再也不用担心我的数据啦

        Room是对SQLite的抽象层,说白了其实就是对SQLite又进行了一层封装,我们不用再频繁的书写sql语句了

        使用步骤

        1.添加依赖

 // ViewModel和LiveData依赖
    implementation "android.arch.lifecycle:extensions:1.1.0"
    annotationProcessor "android.arch.lifecycle:compiler:1.1.0"

    //Room库的依赖
    implementation "android.arch.persistence.room:runtime:1.0.0"
    annotationProcessor "android.arch.persistence.room:compiler:1.0.0"

        2.Modle

public class DataMode extends ViewModel {
    private MutableLiveData<String> data ;
    private MutableLiveData<InfoBean> infobean;

    public MutableLiveData<String> getData(){
        if (null == data){
            //MutableLiveData 是LiveData的子类
            data = new MutableLiveData<>();
        }
        return data;
    }

    public MutableLiveData<InfoBean> getInfobean() {
        if (null == infobean){
            infobean = new MutableLiveData<>();
        }
        return infobean;
    }
}

         3.数据观察者的类

public class DataObserve {
    private static DataMode dataMode;
    private static DataObserve dataObserve;
    private static FragmentActivity mContext;

    public static DataObserve getInstance(FragmentActivity context){
        mContext = context;
        if (null == dataObserve){
            dataObserve = new DataObserve();
        }
        if (null == dataMode){
            dataMode = ViewModelProviders.of(mContext).get(DataMode.class);
        }
        return dataObserve;
    }

    public  void changeData(Observer<String> mObserver){
        //数据只要变化,就会调用
        dataMode.getData().observe(mContext, mObserver);
    }

    public  void setData(String data){
        dataMode.getData().setValue(data);
    }




    public void getDataOfInfoBean(Observer<InfoBean> mObserver){
        dataMode.getInfobean().observe(mContext, mObserver);
    }

    public  void setDataOfInfoBean(InfoBean data){
        /**
         *  数据在主线程变化,则用setValue
         *  如果数据任意线程变化,可使用postValue
         */
        dataMode.getInfobean().setValue(data);
    }
}

        4.写Room时,其实就是一个实体类,一个接口,一个抽象类

//实体类用Entity注解
@Entity(tableName = "info_bean") //tableName 表名, 如果不设置的话,就以类名作为表名
public class InfoBean {
    @PrimaryKey(autoGenerate = true) //将id作为主键,设置为自增长
    @ColumnInfo(name = "infobean_id") //表中的字段名称,如果不设置ColumnInfo,则表中的字段名默认和字段保持一致
    private int id;
    @ColumnInfo(name = "infobean_name")
    private String name;
    private String age;
//    private String address;

//    public String getAddress() {
//        return address;
//    }
//
//    public void setAddress(String address) {
//        this.address = address;
//    }

    public InfoBean(){}

    @Ignore
    public InfoBean(String name, String age) {
        this.name = name;
        this.age = age;
    }

    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 getAge() {
        return age;
    }

    public void setAge(String age) {
        this.age = age;
    }
}

@Dao
public interface InfoBeanDao {
    @Query("select * From info_bean")
    List<InfoBean> getInfoList();

    @Query("select * From info_bean WHERE infobean_id = :id")
    InfoBean getInfo(int id);

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    void addInfo(InfoBean info);

    //删除表中所有
    @Query("DELETE  FROM info_bean")
    int deleteAll();
}

@Database(entities = {InfoBean.class},version = 2,exportSchema = true)//exportSchema true表示导出库文件
public abstract class InfoDataBase extends RoomDatabase{
    private static String db = "info.db";
    private static InfoDataBase infoDataBase;

    public static InfoDataBase getInfoDataBase(Context context) {
        if (null == infoDataBase){
            //初次使用
//            infoDataBase =  Room.databaseBuilder(context.getApplicationContext(),InfoDataBase.class,db).build();

            //这个是数据库升级后,直接清除掉原先的所有数据,慎用!!!
//            infoDataBase = Room.databaseBuilder(context.getApplicationContext(),
//                    InfoDataBase.class, db)
//                    .fallbackToDestructiveMigration()
//                    .build();

            //数据库中的表发生改变
            infoDataBase = Room.databaseBuilder(context.getApplicationContext(),
                    InfoDataBase.class, db)
                    .addMigrations(MIGRATION_1_2)
                    .build();
        }
        return infoDataBase;
    }

    public  void closeDb(){
        infoDataBase.close();
        infoDataBase = null;
    }

    /**
     * 从版本1至版本2  修改了字段id为删除address字段
     * 所以需要添加migrtion的类
     */
    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            //创建个临时表 temp ,切记 使用int类型的数据的时候必须加 NTO NULL DEFAULT 1
            database.execSQL("CREATE TABLE temp (infobean_id INTEGER NOT NULL DEFAULT 1, infobean_name TEXT, age TEXT,PRIMARY KEY(infobean_id))");
            //复制原先表中的数据到临时表temp
            database.execSQL("INSERT INTO temp (infobean_id, infobean_name, age) SELECT infobean_id, infobean_name, age FROM info_bean");
            //删除原先的info_bean表
            database.execSQL("drop table info_bean");
            //将临时表temp改成和原先的表一个名字
            database.execSQL("alter table temp RENAME TO info_bean");
        }
    };


//主要拿到dao的引用
    public abstract InfoBeanDao getInfoBeanDao();
}

以上配置基本就算完成了,必要的注释都在代码中 了,就不再赘述,下来就是在activity中进行数据更改了

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";
    private DataMode dataMode;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button mBtn = (Button) findViewById(R.id.mBtn);
        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int i = (int) (Math.random() * 5);
                DataObserve.getInstance(MainActivity.this).setData("你谁啊"+i);
                if (i == 4){
                    Intent intent = new Intent(MainActivity.this,TestActivity.class);
                    startActivity(intent);
                }

                String[] name = new String[]{"张三","李四","王五"};
                String[] age = new String[]{"23","24","26"};
                int aa = (int)(Math.random() * 3);
                InfoBean infoBean = new InfoBean(name[aa], age[aa]);
                DataObserve.getInstance(MainActivity.this).setDataOfInfoBean(infoBean);
            }
        });

我再这个MainActivity类中进行对数据的设置

public class TestActivity extends AppCompatActivity {
    private static final String TAG = "TestActivity";
    private static final int ADD_DATA = 1;
    private TestActivity mThis ;
    private TextView text_tv;
    private InfoBean infoBean;
    private Handler mHandler;
    private HandlerThread thread;

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

        thread = new HandlerThread("addData");
        thread.start();
        mHandler = new Handler(thread.getLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    case ADD_DATA: //数据的操作必须放在子线程
                        Log.i(TAG, "handleMessage: 数据--"+infoBean);
                        InfoDataBase.getInfoDataBase(mThis).getInfoBeanDao().addInfo(infoBean);
                        List<InfoBean> bean = InfoDataBase.getInfoDataBase(mThis).getInfoBeanDao().getInfoList();
                        Log.i(TAG, "handleMessage: 数据---"+bean.size());
                        int ii = InfoDataBase.getInfoDataBase(mThis).getInfoBeanDao().deleteAll();
                            Log.i(TAG, "handleMessage: 删除---"+ii);
                        for (int i = 0 ; i<bean.size();i++){
                            Log.i(TAG, "handleMessage: "+bean.get(i).getName()+"---"+bean.get(i).getAge());
                        }
                        break;
                }

            }
        };

        initView();
        initData();
        initEvent();

    }

    private void initView() {
        text_tv = (TextView) findViewById(R.id.test_tv);
    }

    private void initData() {
        mThis = this;
    }

    private void initEvent() {
        DataObserve.getInstance(this).changeData(new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                text_tv.setText(s);
            }
        });

        DataObserve.getInstance(this).getDataOfInfoBean(new Observer<InfoBean>() {
            @Override
            public void onChanged(@Nullable InfoBean infoBeans) {
                infoBean = new InfoBean(infoBeans.getName(), infoBeans.getAge());
                Log.i(TAG, "onChanged: "+infoBean.getName()+"---"+infoBeans.getAge());
                mHandler.obtainMessage(ADD_DATA).sendToTarget();
            }
        });


    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        InfoDataBase.getInfoDataBase(mThis).closeDb();
        thread.quit();
        mHandler.removeCallbacksAndMessages(null);
    }
}

在TestActivity类中进行数据的获取

当然也可导出生成的数据库json,需要添加一下操作

defaultConfig {
        ...

        javaCompileOptions {
            annotationProcessorOptions {
                arguments = ["room.schemaLocation":
                                     "$projectDir/schemas".toString()]
            }
        }
    }

这时候就会生成了,如下图

完成!

效果图就不贴了,基本全是打印的 

© 著作权归作者所有

Magic_锋
粉丝 0
博文 58
码字总数 35503
作品 0
东城
程序员
私信 提问
LiveData+ViewMode+Room初次使用

LiveData是持有被观察数据的类,是有生命周期感知的,只有在STARTED和RESUME的状态下才可通知数据的变化, 他的优点就是 再也不用担心oom了 再也不用手动处理生命周期了 实时刷新数据 ViewMode...

Magic_锋
2018/10/29
0
0
哦豁阅读器--oho-reader

哦豁阅读器,API 源自追书神器,免费使用!目前已初步开发完成。 实现追书神器核心功能,做到小说阅读的极简体验,把每一分流量都用到刀刃上。 部分效果截图 实现功能 小说搜索 小说详情 小说...

ShanaMaid
2017/04/11
1K
2
如何用 Javascript 语言实现 SSL协议通讯?

HTTPS协议存在的问题: 1、授权费用高。 2、局域网必须导入证书。 简单的AJAX加密通讯: 页面用HTTP协议传输,只加密AJAX部分。javascript初次访问时获取服务端公钥,然后将公钥永久存储在本...

八风不动
2014/04/15
1K
0
WP7有关定位服务应用审核的注意事项

需要做的: 1、在程序初次启动时询问用户是否开启定位服务 2、提供定位服务的开启/关闭设置 3、告诉用户你怎么使用用户的位置信息,会不会发送给第三方 初次启动弹框,在LOADING页面或者App...

墙头草
2012/01/31
59
0
Parcel 打包器简单使用记录

本文是构造 UI 轮子过程中搭建项目初始化时使用 作为打包器的简要使用记录。 安装 参考 官方文档 使用 进行 的安装。 为什么要用 -D ? 如果一个 包是给用户使用的,不用加 。如果是给开发者...

evenyao
2018/11/02
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CSS3 : transition 属性

本文转载于:专业的前端网站➧CSS3 : transition 属性 CSS3的 transition 属性用于状态过度效果! 1、语法: 1 transition: property duration timing-function delay;2 -moz-transition: ...

前端老手
10分钟前
1
0
一个简单的加密工具,性能貌似不行,待优化

一个简单的加密工具,性能貌似不行,待优化 package com.kxvz.common.crypt;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import java.i......

Kxvz
12分钟前
1
0
vue实现路由懒加载

一、为什么要实现懒加载 减少首屏加载时间,避免白屏 二、常用的懒加载方式有两种:即使用vue异步组件 和 ES中的import a、vue异步加载: import Vue from 'vue' import Router from 'vue-ro...

Bing309
15分钟前
1
0
axios拦截器

axios.interceptors.response.use(response => { if (response.data.code == 0) { return response.data } else if (response.data.code == 600) { Cookies.remove('Admin-Token') router.pu......

Cyoya
17分钟前
1
0
给大家分享下部署云桌面的几个小技巧

从去年4月份开始我们公司就开始使用云桌面来进行上网办公的,在这一年多的使用过程中并没有出现像网上和有些用户说的那样,说云桌面各种坑老是出现这样和那样的问题,而我们之所以用的还不错...

GZASD
17分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部