《第一行代码》总结之广播、数据库(三)

                                                                             第五章详解广播机制

        不得不佩服人的惰性.....要努力啊。

        又学到了四大组件的一个组件BroadCastReceiver,霖神一开始简单谈到了(1)什么是广播机制,(2)然后是接收系统广播(动态注册和静态注册两种,两种都有优势劣势)、(3)自定义广播分为两种,一种是标准广播、一种是有序广播。(4)然后谈到了只能在程序内部传递而且只接受本程序发出的本地广播,(5)最后教给我们如何Git建立本地仓库并上传代码到GitHub。

(一)广播机制简介

         标准广播:异步执行,所有广播接收器在同一时刻收到广播消息,无法被截断;
         有序广播:同步执行,同一时刻只有一个广播接收器接收到消息,有先后顺序,可被后面广播接收器截断。

(二)接收系统广播
         系统广播譬如:电量变化、时间时区变化等。在代码中注册广播称为动态注册,在AndroidManifest.xml中注册称为静态注册     

         2.1动态注册监听网络变化:
        功能:监听网络变化
        实现过程:
        1.定义内部类,继承自BroadcastReceiver,并重写父类onReceive方法,创建广播接收器。
        2.创建intentFilter实例,添加一个action的值,广播接收器想接受什么广播,在这里添加相应的Actiona:**一定要确定对应的Action,android.net.conn.CONNECTIVITY_CHANGE
        3.创建NetworkChangeReceiver实例,调用registerReceiver来进行注册,实现动态监听功能。
        4.ConnectivityManager管理网络服务系统服务类,通过getSystemService获得该实例,getActiveNetworkInfo获取networkInfo实例。通过networkInfo的isAvailable判断当前是否有网络。
       *5.一定要在AndroidMAnifest.xml中设置权限声明。

        *6.动态注册的广播一定要取消注册才行。unregisterReceiver注销广播。

        2.2 静态注册实现开机启动
       动态注册优势是灵活性高,缺点是必须启动之后才能接收到广播,而静态注册程序未启动就能接收到广播。
       功能:开机启动弹窗
       实现步骤: 

      1.右击包名->new->Other->BroadCast Receiver。勾选exported和enabled,exported允许广播接收器接收本程序之外的广播,enabled选择启用该广播接收器。
      2.修改BootCopleteReceiver的代码,实现一个弹窗功能;
      3.在Receiver中的添加相应Action,此Action为:

     4.声明相应的权限:

      这个不用注销掉广播哈,然后很恶心的一点是每次开机后十几秒才弹出弹窗,让我误以为不弹,各位老铁请注意。然后BootCopleteReceiver的onReceiver方法不能填加过多逻辑和耗时操作。若长时间不结束,会报错。

    (三)发送自定义广播
     刚才说到了系统广播,然后我们来看看自定义广播。
     3.1 发送标准广播
     1.新建广播接收器Broadcast_01,弹出弹窗,AndroidMainfest.xml中对于该receiver的intent_filter进行修改,接收到一条值为  nwu.hzk.p177.My_broad的广播。
     2.MainActivity中建立按钮,用于发送广播触发点,构建Intent对象,将发送的广播植入,使用sendBroadcast(intent);发送广播,所有监听该广播的接收器就会接收到该消息。

     3.2 发送有序广播
     1.新建程序,注册接受广播Broadcast_02,让其接收上一个程序发送的nwu.hzk.p177.My_broad广播;
     2.Broadcast_01将sendBroadcast(intent);变为sendOrderedBroadcast(intent,null);
     3.再将Broadcast_02中receiver的intent_filter的优先级android:priority="100"设置为100;
     4.在Broadcast_02中调用abortBroadcast();中断广播传递,这样Broadcast_01就不会接收到广播啦。

    (四)使用本地广播
      本地广播机制支持能在程序内部传递而且只接受本程序发出的广播。
      与动态注册广播有一点点区别,大致一样:
      1.使用LocalBroadcastManager的getInstance去获取一个实例;
      2.发送广播接收器的时候是localBroadcastManager.sendBroadcast(intent);//发送
      3.信号自己定。

     (五)强制下线功能。
     这块并不难,只是说自己觉得人写的高明的几点:
     1.建立ActivityCollector来管理所有活动,添加活动,删除活动,结束所有活动;
     2.创建BasicActivity作为所有活动父类。复写Oncreate和OnDestroy方法;
     3.建立布局和响应点击事件,判断是否相等跳到MainActivity相应界面;
     4.在Activity实现广播的发送。
     5.在BasicActivity实现广播的监听,在onResume()方法中实现广播监听的注册,广播监听注册的ForceOfflineReceiver是一个AlterDialog,然后点击ok键是销毁所有活动,启动登录界面的操作,因为此时活动一定处于返回栈栈顶,准备好和用户进行交互时调用;在onPause()方法中实现广播的注销,因为此时系统去启动或者回复另一个活动的时候调用,当一个活动失去栈顶位置时会自动取消广播接收器的注册。
     6.改变主函数的入口,从MainActivity改到LoginActivity

   (六)Git-初识版本控制工具
     是一款分布式版本控制工具。下面来教教大家如何使用Git建立本地仓库并上传代码到GitHub
     1.到本地项目文件夹右键选择git bash here
     2.输入个人信息(代码提交者)

git config --global user.name "xxxx" 
git config --global user.email [email protected] 

     3.在本地项目目录创建本地仓库,输入命令后项目目录会有一个隐藏的.git文件夹

git init  

     4.上传所有代码到本地仓库

git add .
git commit -m "initial commit"

     5.上传代码到github
     新建repository,复制仓库地址《第一行代码》总结之广播、数据库(三)_第1张图片

       6.关联本地仓库并上传代码

git remote add origin ***.git(刚才复制的仓库地址)
git push origin master

 

                                                                    第六章   数据存储全方案-持久化技术
        保存在内存中的数据是瞬时状态的,保存在存储设备中的数据是处于持久状态的,文件存储、SharedPerference存储和数据库存储三种方式。(1)文件存储就是利用输入输出流等Java常用的方法将文件写入,可以用于存储文本或二进制数据;(2)SharedPreferences用于存储键值对,可以支持不同类型的数据;(3)SQLite可以存储复杂的关系型数据库,实现创建、增删查改等功能。(4)作者维护的一个开源库LitePal,相比于SQLite,它采用对象关系映射(ORM)的模式,对数据库功能进行封装,较为简单。利用对象的思想去解决关系型数据库的问题,什么时候自己能维护一个就厉害了。
(一)文件存储
        不做格式化处理,原封不动存储文本数据和二进制数据。
        1.1.将数据存储到文件中
       第一步:openFileOutput将数据存储到指定的文件当中去。第一个是文件名,第二个是文件的操作模式,MODE_PRIVATE为默认,会覆盖之前内容,APPEND会追加内容。默认存储到/data/data/pacak name/file下
       第二步:获得FileOutputStream对象,借助他构建OutputStreamWriter对象,在构建BufferedWriter对象,使用Java流方式将其写到文件当中去。
       第三步:输入结束关闭输入流。
       第四步:onDestroy中复写存储方法,确保活动销毁之前调用save方法。
      查看好像不太好查看,在Android Device Monitor中没有看到file文件下的data。(可能需要刷机吧)

       1.2.从文件中读取数据
       第一步.openFileInput获得FileInputStream对象;
       第二步.借助上一步结果构建InputStreamReader对象,在构建BufferedReader对象,再一行行构读取文本中的所有内容,存放至Stringbuilder对象中去。读取并返回,关闭Reader流。
       第三步.在onCreate方法中调用load()方法,获取字符串。!TextUtils.isEmpty(inputText)判断字符串不为null或空时,setText设置字符串。使用editText.setSelection(inputText.length());将光标移至末尾。
       此方法不适合保存一些复杂的文本数据,故而....我们来看下一种存储方式。

(二)SharedPreferences存储
       使用键值对存储数据,支持多种不同类型数据存储。
       2.1将数据存储至SharedPreferences中
       第一步.使用三种方法获得SharedPreferences对象,第一种是getSharedPreferences:参数是文件名和指定的操作模式;第二种是getPreferences获得对象,只有一个参数,文件名类名;第三种是getDefaultPreferences,程序包名存储。
       第二步.SharedPreferences的edit方法获取editor对象。
       第三步.在Editor对象中添加数据,比如添加布尔类型putBoolean,添加字符串putString
       第四步.将添加的数据进行提交。
       
        2.2从SharedPreferences中拿数据
       第一步.getSharedPreferences获得sharedPreferences对象;
       第二步.getString、getInt获得相应数值,若没有,则用后面的默认值替代。
       第三步.logd输出

       2.3实现记住密码功能
       复用P185代码。需要注意的有以下几点:
      1.加入复选框,如果选定就记住密码,若没有选中就不记住密码。
      2.点击之后会将几个值存进sharedPreferences中,用boolean类型更改为true。下一次在执行OnCreate的时候讲boolean,用户名,密码setText和setChecked进去。刚开始默认boolean是false。
      很简单。

(三)SQLite
       轻量级关系型数据库,速度快,占用资源少,遵循数据库ACID事务。当存储度咋的关系型数据库时,以上两种存储方式就会有比较大的问题。
       3.1创建数据库
       SQliteHelper帮助类来对数据库进行创建和升级。其中有两个抽象方法。分别是onCreate和onUpgrade,在这两个方法中创建和升级数据库的逻辑。使用getReadableDatabase()和getWritableDatabase()来创建或打开一个数据库。主分为以下几步:
       (1).创建MyDatabaseHelper继承自SQLiteHelper,创建数据库的语句,将建表语句定义成字符串常量。

 public static final String CREATE_BOOK = "create table Book("
            +"id integer primary key autoincrement,"
            +"author text,"
            +"price real,"
            +"pages integer,"+"name text)";

      (2).在onCreate调用SQLiteDatabase的execSQL执行这条建表语句,弹出Toast提示成功。
      (3).创建相应的布局。
      (4).MyDatabaseHelper的getWritableDatabase方法创建并打开数据库。Adb shell如何配置于系统中,进入相应的Database目录下,ls命令看里面内容(必须要root权限),sqlite3 BookStore.db打开数据库;.table查看哪些表;.schema查看建表语句。

       3.2升级数据库
     (1).在Book表基础之上再添加Category表;
     (2).在onUpgrade中增加两条Drop语句,若存在则删除该表,并转而执行onCreate方法;
     (3)在onCreate方法中执行创表语句;
     (4)dbHelper = new MyDatabaseHelper(this,"BookStore.db",null,2);将版本号改为比1大的。

      3.3 添加数据
      数据操作无非就是4种。C(Create添加->insert)R(Retrieve查询->select)U(Update更新->update)D(Delete删除->delete),调用SQLIteOpenHelper的getWritableDatabase可以用于创建和升级数据库,而且其会返回一个SQLiteDatabase对象供我们去进行GUID操作。示例如下: 

SQLiteDatabase db = dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
//1.开始组装并插入第一条数据;
values.put("name","The Da Vinci Code");
values.put("author","Dan Brown");
values.put("pages",454);
values.put("price",16.96);
db.insert("Book",null,values);
values.clear();

      3.4 更新数据库

     首先构建一个ContentValues对象,指定更改后的数据,调用SQLiteDatabase的update对象,第三个参数对应SQL语句的where部分,表明更新所有name等于?的行,而?相当于一个占位符,第四个参数为占位符指定的内容。

SQLiteDatabase db=dbHelper.getWritableDatabase();
ContentValues values = new ContentValues();
values.put("price",10.99);
db.update("Book",values,"name=?",new String[]{"The Da Vinci Code"});

      3.5 删除数据库
      没什么好说的。很简单。

SQLiteDatabase db = dbHelper.getWritableDatabase();
db.delete("Book","pages>?",new String[]{"500"});
//通过第二三参数来删除页数超过500的书。

      3.6查询数据
     较为复杂,总共七个参数;调用query之后会返回一个Cursor对象。查询到的数据从中取出。
    (1)db.query("Book",null...)查询Book表中的所有数据,并将数据以Cursor对象进行返回。
    (2)将数组指针通过moveToFirst移到第一行的位置。
    (3)遍历Cursor对象,取出数据并打印,通过getColumnIndex获取某一列在表中对应的位置索引,然后将这索引传入到相应的取值方法中,这样便可以得到从数据库中读取到的数据了。
    (4)Log输出。moveToNext获取下一条数据。
    (5)调用Close方法来关闭Cursor流。

     3.7使用SQL操作数据库

                          《第一行代码》总结之广播、数据库(三)_第2张图片

(四)LitePal
       LitePal是一款开源数据库框架,采用对象关系映射(ORM)的模式,对数据库功能进行封装,较为简单。
       4.1配置LitePal
      (1)Build.gradle中的dependencies中添加compile 'org.litepal.android:core:1.3.2'
      (2)在main目录下建立assets目录,在assets目录下建立litepal.xml,编辑里面内容。指定相应的数据库名、数据库版本名、以及list所指的所有映射模型。
      (3)在AndroidManifest.xml中增加Appliacation配置 

android:name="org.litepal.LitePalApplication"

      4.2创建和升级数据库
     (1)建立Book类,定义id、author、price、pages、name这几个字段及相应的get和set方法,每个字段对应表中的每一列。
     (2)将Book类添加至4.1的第(2)中的List中。

    (3)在MainActivity中进行Connector.getDatabase();完成一次最简单的数据库操作,这时数据库就会自动创建完成了。
    (4)升级数据库的话,若是在一张表里面添加列,则只需要在Book中添加相应的变量名和相应的set和get方法;若是需要添加表,则新建Category类并在list映射模型中添加新的模型类。

      4.3使用LitePal添加数据
    (1)先将模型类继承自DataSupport类,这样才能进行GUID操作;

public class Book extends DataSupport{

    (2)创建出Book的实例,然后各种set方法,最后调用book.save()方法完成数据添加操作。

    4.4使用LitePal更新数据库
   (1)对已存储的对象进行操作;直接setPrice()对价格进行修改,然后save完成该条数据的更新。
   (2)更为灵活的更新书名、印刷商。更新所有该条件判断语句下的对象。

Book book = new Book();
book.setPrice(14.95);
book.setAuthor("Anchor");
book.updateAll("name=? and author=?","The Lost Symbol","Dan Brown");

     (3)将Pages字段更新为默认值。

Book book = new Book();
book.setToDefault("pages");
book.updateAll();

     4.5使用Litepal删除数据
    DataSupport.deleteAll删除数据,第一个参数用于指定那个表,第二个和第三个是约束条件。

  DataSupport.deleteAll(Book.class,"price < ?","15");

    4.6利用LitePal查询数据
    使用List books = DataSupport.findAll(Book.class);来获取Book类型的List集合。然后再行输出即可。

    4.7其他操作语句

《第一行代码》总结之广播、数据库(三)_第3张图片

《第一行代码》总结之广播、数据库(三)_第4张图片

你可能感兴趣的:(安卓开发,第一行代码&安卓开发艺术探索)