《第一行代码》学后知识小总结

Android知识学习总结

android四大组件:

1、活动(Activity

2、广播(Broadcast
3、服务(Service
4、内容提供器(ContentProvider
四大组件的超类都是Context

 
 
Activity

包含用户界面的组件,主要用于和用户进行交互

状态:运行状态、暂停状态、停止状态、销毁状态

生命周期:

onCreate()

onStart()

onResume()

onPause()

onStop()

onDestroy()

onRestart()


启动模式:

standard

singleTop

singleTask

singleInstance

AndroidMenifest.xml中设置activity的属性可以更改它的启动模式

(android:launchMode=””)


活动间传递数据:Intent

显式Intent

Intentintent = new Intent(A.this, B.class);

startActivity(intent);

隐式Intent

<activity...>

<intent-filter>

<actionandroid:name=”a”/>

 //默认的
<categoryandroid:name=”android.intent.category.DEFAULT”/>

</intent-filter>

</activity>
 
 
Intentintent = new Intent(“a”);

startActivity(intent);

<activity...>

<intent-filter>

<actionandroid:name=”a”/>

<categoryandroid:name=”android.intent.category.DEFAULT”/>

<categoryandroid:name=”b”/>
 
 
</intent-filter>

</activity>
 
 
Intentintent = new Intent(“a”);

intent.addCategory(“b”);

startActivity(intent);

 
 
//调用系统浏览器(其他程序的活动)

Intentintent = new Intent(Intent.ACTION_VIEW);

intent.setData(Uri.parse(“http://www.baidu.com”));

startActivity(intent);

//跳至系统拨号页面

Intentintent = new Intent(Intent.ACTION_DIAL);

intent.setData(Uri.parse(“tel:10086”));

startActivity(intent);
 
 
传数据:putExtra(key,value);

接收:getStringExtra()getIntExtra() getBooleanExtra()

向上一个活动返回数据:

Intentintent = new Intent(A.this, B.class);

startActivityForResult(intent,1);

A中重写onActivityResult()B被销毁后会回调上一个活动即AonActivityResult()
 
 
利用Intent传对象

Bundlebundle = new Bundle();

bundle.putSerializable(“user”,user);

intent.putExtras(bundle);

接收:

Useruser = intent.getSerializableExtra(“user”);

或者

Bundlebundle = new Bundle();

bundle.putSerializable(“list”,(Serializable)list);

intent.putExtras(bundle);

接收:

List<User>list = intent.getSerializableExtra(“list”);
 
 

Broadcast

标准广播Normalbroadcasts完全异步执行的广播,广播一发出sendBroadcast(..),

所有的广播接收器几乎会在同一时刻接收到这条广播消息,

效率较高,无法被截断

有序广播Orderedbroadcasts同步执行的广播,广播发出后sendOrderedBroadcast(..),

优先级高的先收到广播,可以在AndroidMenifest

中对应的<receiver>标签中设置优先级<intent-filterandroid:priority=10>,默认为0,

值越大优先级越高,范围是[-1000,1000],前

面的广播接收器收到后还可以截断该广播abortBroadcast()
 
 
广播接收器注册广播(定义自己能收到的广播是什么):

AndroidMenifest.xml中,对于每一个广播接收器都会进行注册,即<receiver>标签。

动态注册及发送

先写个广播接收器,eg:...class NetworkChangeReceiver extends BroadcastReceiver

重写onReceive()

然后在代码中注册(一般在初始化代码里):

IntentFilterintentFilter = new IntentFilter();

intentFilter.addAction(“Broadcast1”);

NetworkChangeReceivernetworkchangeReceiver = new NetworkChangeReceiver();

registerReceiver(networkchangeReceiver,intentFilter);

注意:动态注册的广播接收器要在onDestroy()中注销unregisterReceiver(networkchangeReceiver)

发送Intentintent = newIntent(“Broadcast1”);sendBroadcast(intent);后,会回调

接受该广播的广播接收器的onReceive()方法。

如果发送的是有序广播sendOrderedBroadcast(),可以在onReceive()里实现广播截断。

 
 
静态注册及发送:

如果要静态注册该广播接收器想要接收的广播,可以在<receiver>标签里添加<intent-filter>

标签,并在其中添加<action<category等属性。

发送如上

 
 
动态及静态注册的区别:动态注册的广播接收器可以自由的控制注册和注销,灵活性较好,但是它必须

要在程序启动之后才能接收到广播,而静态注册在

程序未启动的情况下就可接收到广播。

 
 
 
 
关于本地广播

为了解决广播的安全性问题,使用本地广播机制发送的广播只能在本应用程序内部进行传递,并且广播

接收器也只能接收来自本应用程序发出的广播。

代码与动态注册广播并发送的代码几乎一样,只是用LocalBroadcastManager来对广播进行管理。

(本地广播不能用静态注册的方式接收)

LocalBroadcastManagerlocal = LocalBroadcastManager.getInstance(this);


local.sendBroadcast(intent);

local.registerBroadcast(广播接收器实例,intentFilter);

local.unregisterBroadcast(广播接收器实例);

 
 
优势:

可以明确的知道正在发送的广播不会离开我们的程序,不用担心机密数据泄露的问题

其他的程序无法将广播发送到我们程序的内部,因此不需要担心会有安全漏洞的隐患

发送本地广播比发送系统广播更高效



Service

适于执行不需要和用户交互但又要求长期运行的任务。

服务的运行不依赖于任何用户界面,依赖于创建服务时所在的应用程序进程

异步消息处理机制

MessageHandlerMessageQueueLooperAsyncTask

Handler主要用于发送和处理消息,发送:HandlersendMessage(Messagemsg)方法,消息会

传到HandlerhandleMessage()中。

MessageQueue主要用于存放所有通过Handler发送的消息

Looper是每个线程中MessageQueue的管家,每当发现MessageQueue里存在一条消息,就会将它

取出,并传到HandlerhandlerMessage()方法中。

异步消息处理流程:

先创建一个Handler对象,并重写handlerMessage()方法,当子线程中需要进行UI操作时,就创

建一个Massage对象,并通过Handler将消息发出去,

之后这条消息会被添加到MessageQueue的队列中等待被处理,然后Looper会一直尝试从队列中取出

待处理消息,分发到HandlerhandlerMessage中

进行处理。

 
 
AsyncTask是一个抽象类,需要创建子类去继承它,继承时可以为AsyncTask类指定三个泛型参数

Params执行AsyncTask时需要传入的参数,可用于在后台任务中使用;

Progress后台任务执行时,若需要在界面上显示当前的进度,则使用这里的泛型作为进度单位;

Result当任务执行完毕后,若需要对结果进行返回,则使用这里指定的泛型作为进度单位

以上三个参数的可取值为:IntegervoidBoolean等泛型

 
 
该子类还需要重写以下几个方法才能完成对任务的定制

onPreExecute():

在后台任务开始执行前调用,用于进行一些页面上的初始化操作,比如显示一个进度条对话框

doInBackground(Params…):

该方法的所有代码都在子线程中运行,用于处理所有的耗时任务,任务一旦完成就可通过return语句

来将任务的执行结果返回,如果第三个泛型参数为

void,就可以不用返回任务执行结果,该方法中不能进行UI操作,如果有UI元素需要更新,就可以在

方法中调用publishProgress(Progress...)

来完成

 
 
onProgressUpdate(Progress…)

当后台调用了publishProgress(Progress...)方法后,该方法很快也会被调用,在该方法中可

以对UI进行操作

onPostExecute(Result):

当任务执行完毕并通过return语句进行返回时,该方法就很快会被调用,返回的数据会作为参数传

到该方法中,可以进行UI操作
 
 

使用AsyncTask
启动AsyncTask:子类实例对象.execute()

doInBackground()中执行具体的耗时操作,在里面调用publishProgress()方法进入

onProgressUpdate(),在onProgressUpdate()中执行

UI操作,在onPostExecute()中执行一些任务的收尾工作
 
 

Service的基本用法

抽象类,需要用子类实现它,Service有一个唯一的抽象方法onBind(),服务常用的三个方法:

onCreate()服务创建时调用、onStartCommand()每次服务启动时调用、onDestroy()服务

销毁时调用。

服务的启动和停止:

借助Intentintent= new Intent(this, MyService.class);

开始:Activity中调用startService(intent);

停止:由活动控制Activity中调用stopService(intent); 

由自己控制Service中调用stopSelf()
 
 
可以借助onBind()来加深活动与服务的联系,活动指挥服务

MyService中:创建一个Binder对象:用一个子类MyBinder继承Binder,写自己的逻辑方法,

onBind()里返回这个Binder对象。

Activity中:创建ServiceConnection匿名类,重写onServiceConnnected()

onServiceDisconnected(),分别在活动与服务成功绑定及

连接断开时调用。

privateServiceConnection connection = new ServiceConnection(){

//重写onServiceConnnected()onServiceDisconnected()
…… 

//onServiceConnnected()可以将参数IBinder对象向下转型为MyBinder对象,就可以调用

//MyService.MyBinder中的方法了

}
通过bindService(intent,connection, xxx)绑定服务

xxx可以为BIND_AUTO_CREATE,表示活动与服务绑定后自动创建服务。

通过unbindService(connection)断开连接

 
 
每个服务在整个应用程序内都是通用的,可以和多个活动绑定。

 
 
服务的生命周期:

调用startService()后,服务启动,回调onStartCommand(),如果该服务之前并未被创建,

onCreate()会先于onStartCommand()执行,

一直到调用stopService()stopSelf(),服务停止。

调用bindService()后,回调onBind(),如果该服务之前并未被创建,onCreate()会先于

onBind()执行,只要连接没有断开,服务就会一直

处于运行状态。

调用bindService()之后调用了unbindService()onDestroy()会被调用;调用

startService()之后调用了stopService()onDestroy()会被调用;如果bindService()

startService()都被调用了,则只有unbindService()stopService()都被调用之后,

onDestory()才会被执行。

 
 
服务的更多技巧

前台服务 

Intentintent = new Intent(this, MainActivity.class);

PendingIntentpi = PendingIntent.getActivity(this, 0, intent, 0);

Notificationnotification = new NotificationCompat.Builder(this)

                .setContentTitle(“title”)
               
                .setContentText(“text”)

                .setSmallIcon(R.mipmap.ic_launcher)

                .setLargeIcon(BitmapFactory.decodeResources(),
                   
                                    R.mipmap.ic_launcher)

                .setContentIntent(pi)

                .build();

startForeground(1,notification);

 
 
IntentService:异步的、会自动停止的服务。

抽象类,需要一个子类继承它,构造方法中,需要实现父类的有参构造方法,实现onHandleIntent()

抽象方法
 
 

ContentProvider

运行时权限:

Android中危险权限共924个,需要用户手动授权才能启用,我们在进行运行时权限处理时使用的

是具体的权限名,但是用户一旦同意授权了,

那么该权限所在的一个权限组中所有的其他权限也会同时被授权

eg:拨打电话Intent.ACTION_CALL需要声明权限

首先在AndroidMenifest.xml中,声明权限

<uses-permissionandroid:name=”android.permission.CALL_PHONE”>

在低于Android6.0系统的手机上就可以了,但6.0及更高版本的手机上会报错:

PermissionDenial,需要对权限进行处理

例如调用系统对话框申请权限:

if(ContextCompat.checkSelfPermission(MainActivity.this,Manifest.permission.

                        CALL_PHONE) !=PackageManager.PERMISSION_GRANTED){

//系统对话框,请求权限,输入一个请求码(固定值)

ActivityCompat.requestPermission(MainActivity.this,new

String[]{Mainifest.permission.CALL_PHONE},1);

}

else{

call();

}

//ActivityCompat.requestPermission()的回调函数

publicvoid onRequestPermissionResult(int requestCode, String[] permissions,

                       int[] grantResults) {

switch(requestCode){

//请求码

case1:

      //请求赋权结果存放在grantResults数组里

if(grantResults.length > 0&& grantResults[0] ==

PackageManager.PERMISSION_GRANTED){

call();

}

else{

Toast.makeText(this,“You denied the

permission”,Toast.LENGTH_SHORT).show();

}

break;

default:

break;

}

}
 
 
跨程序访问数据

ContentResolver的基本用法:

每个应用程序要想访问内容提供器中共享的数据,一定要借助ContentResolver类,可以通过

Context中的getContentResolver()

方法获取该类实例。

ContentProvider中的增删改查方法均不接受表名参数,使用一个唯一的uri参数代替,即内

容uri,由authoritypath组成,

authority对不同的应用程序做区分,path对不同的表做区分,内容URI格式例子:

content://com.example.app.provider/table1

内容URI字符串需要通过Uri.parse(“内容uri字符串”)被解析成uri对象

 
 
一般通过URI判定是用的自定义的Provider还是利用的现有的Provider,因为自定义的Provider

会在Menifest文件中注册,并声明

anthorities属性,uri若是系统封装好了的,则使用的现有的Provider,若是自定义的uri,则

必有对应的Provider被定义。
 
 

Cursorcursor = getContentResolver().query(uri, projection, selection,

selectionArgs, sortOrder);

if(cursor!= null) {

where(cursor.moveToNext){

Stringcolumn1 = cursor.getString(cursor.getColumnIndex(“column1”));

intcolumn2 =

cursor.getInt(cursor.getColumnIndex(“column2”));

Log.d(“aaaaa”, column1 +“, ” + column2);

}

}
 
 
CotentValuesvalues = new ContentValues();

values.add(“column1”,”text”);

values.add(“column2”,“1”);

getContentResolver().insert(uri,values);

 
 
ContentValuesvalues = new ContentValues();

values.put(“column1”,“aaaa”);

getContentResolver().update(uri,values, “column1 = ? and column2 = ?”,

 new String[]{“text”,“1”});
 
 

getContentResolver().delete(uri,“column2 = ?”, new String[]{“1”});
 
 

创建自定义内容提供器

新建一个类继承ContentProvider来创建自己的内容提供器,实现它的6个抽象方法:

onCreate()

只有当ContentResolver尝试访问我们程序中的数据时,内容提供器才会被初始化

query(uri, projection, selection, selectionArgs, sortOrder)

调用db.query()来查询,将查询结果放在cursor中返回

insert(uri, contentValues)

添加成功后,返回一条用于表示这条新记录的URI

update(uri, contentValues, selection, selectionArgs)

返回受影响的行数

delete(uri, selection, selectionArgs)

返回被删除的行数

getType(uri)

返回对应的MIME类型(String

MIME字符串:

@ 1必须以vnd开头

@ 2 若内容uri以路径结尾,则后接android.cursor.dir,若以id结尾,则接

       android.cursor.item/

@ 3  最后接上vnd.authority.path
 
 

内容uri还可以在以路径结尾的内容uri上添加一个id,表示期望访问该表中id为多少的数据。

Eg:……app.provider/table2/1

或者也可用通配符来匹配以路径结尾或以id结尾的这两种格式。

Eg:…… app.provider/*匹配任意表的URI格式(*匹配任意长度的任意字符)
  
  ……app.provider/table1/#匹配table1表的任意行数据(#表示匹配任意长度的数字)

 
 
利用UriMatcher类实现匹配内容URI的功能

uriMatcher.addURI(authority,path,自定义代码)

eg:…… static final int TABLE_ITEM = 0;……

UriMatcheruriMatcher = new UriMatcher(UriMatcher.NO_MATCH);

uriMatcher.addURI(“com.example.app.provider”, “table/#”, TABLE_ITEM);

通过uriMatcher.match(uri)来获取对应的自定义代码

 
 
 
 
数据存储

文件存储:存储一些简单的文本数据或二进制数据

SharedPreferences存储:存储一些较为复杂的文本数据

SQLite数据库存储:存储一些复杂的关系型数据

 
 
文件存储:

openFileOutPut(“文件名”,文件操作模式)写出数据到文件中

文件名不可包含路径,所有文件均默认存储到/data/data/<packagename>/files/目录下

文件操作方式默认为MODE_PRIVATE,即当指定同样文件名时,会覆盖掉原文件中的内容,

MODE_APPEND表示如果该文件已存在则在该文

件中追加,不存在就创建新文件

Stringdata = “this is data to write”;

FileOutputStreamout = null;

BufferdWriterwriter = null;

 
 
out= openFileOutPut(“file1”, Context.MODE_PRIVATE);

writer= new BufferdWriter(new OutputStreamWriter(out));

writer.write(data);

 
 
openFileInPut(“文件名”)从文件中读进数据

FileInputStreamin = null;

BufferdReaderreader = null;

StringBuildercontent = new StringBuilder();

 
 
in= openFileInput(“file1”);

reader= new BufferdReader(new InputStreamReader(in));

Stringline = “”;

while((line= reader.readLine()) != null) {

content.append(line);

}
 
 
SharedPreferences存储

采用键值对方式存储数据,支持多种不同的数据类型

SharedPreferences文件都存放在/data/data/<packagename>/shared_prefs/目录下,

SharedPreferences文件使用XML格式来对数据进行管理

写数据:

1、先得到SharedPreferences对象;

Context类中的getSharedPreferences()方法、Activity类的getPreferences()方法、

PreferencesManager类中的getDefaultSharedPreferences()方法。

2、然后调用SharedPreferences对象的edit()方法获取一个SharedPreferences.Editor对象;

3、向SharedPreferences.Editor对象中添加数putBoolean()putString()

4、调用apply()将添加的数据提交

SharedPrefernces.Editoreditor = getSharedPreferences(“share1”,      
               
             MODE_PRIVATE).edit();

//只有一种操作模式,也是默认模式,传入0效果一样

editor.putString(“name”,“Tom”);

editor.putInt(“age”,12);

editor.putBoolean(“married”,false);

editor.apply();

 
 
 
 
读数据:

1、先得到SharedPreferences对象;

Context类中的getSharedPreferences()方法、Activity类的getPreferences()方法、

PreferencesManager类中的

getDefaultSharedPreferences()方法。

2、通过SharedPreferences对象的get方法获取文件中的内容

getString(key)getInt(key)……

SharedPreferncespref = getSharedPreferences(“share1”, 
     
               MODE_PRIVATE);

Stringname = pref.getString(“name”);

intage = pref.getInt(“age”);

booleanmarried = pref.getBoolean(“married”);

 
 
 
 
SQLite数据库存储

新建一个类MyDatabaseHelperextends SQLiteOpenHelper帮助类,

实现onCreate()onUpgrade()抽象方法,有两个构造方法可供重写,一般选择参数少的重写,

SQLiteOpenHelper还有两个实例方法,getReadableDatabase()getWritableDatabase(),

这两个方法都可以创建或打开一个现有的数据库,并返回一个可对数据库进行读写操作的对象,当数据库

不可写入时,getReadableDatabase()返回的对象将以只读方式去打开数据库,而

getWriteableDatabase()将会出现异常。

创建表

real浮点型 blob二进制类型
 
Stringcreate_book = “create table Book (id integer primary keyantoincrement, 

author text, price real, pages integer)”;

Stringcreate_category = “create table Category (…… )”;

…… 

…… onCreate(SQLiteDatabase db){

db.execSQL(create_book);db.execSQL(create_category);…… }
 
…… onUpgrade(SQLiteDatabase db,int oldVersion, int newVersion){

db.execSQL(“drop table ifexists Book”);

db.execSQL(“drop table ifexists Category”);

onCreate(db); 

}

 
 
添加数据

privateMyDatabaseHelper dbHelper;

…… 

SQLiteDatabasedb = dbHelper.getReadableDatabase();

ContentValuesvalues = new ContentValues();

values.put(key,value);…… //key列名 value
db.insert(“表名”,null, values);

values.clear(); //清空values

values.put(key,value);…… //继续添加

db.insert(“表名”,null, values); //第二个参数用于在未指定添加数据的情况下给某些可

为空的列自动赋值null,一般赋null
 
 

更新数据

db.update(“表名”,ContentValues对象,selections, selectionArgs);

//values可以只有一个或几个列的值

SQLiteDatabasedb = dbHelper.getReadableDatabase();

ContentValuesvalues = new ContentValues();

values.put(“price”,12.34);

db.update(“Book”,values, “name = ?”, new String[]{“The First Book”});

 
 
删除数据

db.delete(“表名”,selections, selectionArgs);

db.delete(“Book”,“page > ?”, new String[]{“500”});

 
 
查询数据

db.query(“表名”,columns, selection, selectionArgs, groupBy, having, orderBy);

Cursorcursor = db.query(“Book”, null,null,null,null,null,null);

if(cursor.moveToFirst){

do{

Stringname =

cursor.getString(cursor.getColumnIndex(“name”));

……getDouble()getInt()

}while(cursor.moveToNext());

}

cursor.close();

 
 
使用SQL操作数据库

db.execSQL(“insertinto Book (name, author, …… )values(?,?,……)”, 

           new String[]{“TheFirst Book”, “Tom”, ……});

db.execSQL(“updateBookset price = ? where name = ?”,

           new String[] {“12.34”, “TheFirst Book”});

db.execSQL(“deletefromBook where page > ?”, newString[]{“50”});

db.rawQuery(“select* from Book”, null);

 
 
 
 
 
 
拓展:

getClass.getSimpleName()获取当前实例的类名

getTaskId()获取返回栈的IdActivity都被放在返回栈中。

 
 
UI相关

重写onBackPressed()可以自定义Back建的功能

imageview.setImageResource() 设置ImageView的背景图片

setVisibility();设置控件是否可见(android:vidibility
visible可见 invisible不可见但占空间 gone不可见且不占空间

 
 
进度条:ProgressBar默认为圆形

style=”?android:attr/progressBarStyleHorizontal”可设为水平进度条  

android:max设最大值,setProgress()getProgress()

 
 
AlertDialogProgressDialog可在界面上弹出一个对话框,ProgressDialog会在对话框中

显示一个进度条,表示当前操作比较耗时,


请用户耐心等待

progressDialog.setCancelable(false)表示按back键不能取消,须在代码中控制:当数据

加载完后调用ProgressDialogdismiss()


来关闭对话框,否则progressDialog将会一直存在。
 
 

4种基本布局:

线性布局LinearLayout、相对布局RelativeLayout、百分比布局(PercentFrameLayout/

 PercentRelativeLayout)、帧布局(FrameLayout)

百分比布局:

要在app/build.gradledependencise闭包里添加百分比布局的依赖库

(compile‘com.android.support:percent:24.2.1’,xml布局里可以

<android.support.percent.PercentFrameLayout..

android:heightPercent=”10%” android:widthPercent=”20%”

 
 
引入布局:

<includelayout=”@layout/布局文件名”

隐藏系统自带标题栏:

ActionBaractionbar = getSupportActionBar();

if(actionbar!= null){ actionbar.hide(); }
 
 
 
android:inputType属性用来设置文本的类型,用于帮助输入法显示合适的键盘类型。

android:inputType="取值如下"

textEmailSubject 邮件主题   
textShortMessage 短信息(会多一个表情按钮出来)
textLongMessage 长讯息
textPersonName 人名
textPostalAddress 地址
textPassword 密码    textVisiblePassword 可见密码
datetime时间日期    date日期    time时间
android:inputType="phone" 拨号键盘
android:inputType="textCapWords" 单词首字母大小
android:inputType="textCapSentences" 仅第一个字母大小
android:inputType="number" 数字格式
android:inputType="numberSigned" 有符号数字格式
android:inputType="numberDecimal" 可以带小数点的浮点格式
android:inputType="phone" 拨号键盘
 
 
EditText

mEditText.setSelection(intindex);设置光标的位置

 
 
Button

mButton.setEnabled(false);按钮元素不可见
 
 
 
 
 
 
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值