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

来源:互联网 发布:小米网络电视怎么用 编辑:程序博客网 时间:2024/06/05 07:44
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);按钮元素不可见
原创粉丝点击