最近郭霖大神的第二行代码出版了,我也是第一时间买到了这本书,并且刷完了一遍。作为安卓开发的初学者,想梳理一下书中的主要知识点,以作备忘之用。这也是我的第一篇博客,希望在以后的学习和工作中可以经常记录一些内容,供自己参考,也能和大家分享与交流。
一、 Acitivity
(一) 用法
1. 加载布局
setContentView(R.layout.activity_main);
2. AndroidManifest中注册
<activity android:name=".FirstActivity"
android:lable="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.category.LAUNCHER" />
</intent-filter>
</activity>
3. 使用Menu
(1) res文件夹下新建menu文件夹,在其中新建菜单文件main.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu>
(2) 重写 onCreateOptionsMenu() 使菜单显示出来
重写快捷键Ctrl+O
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
(3) 重写 onOptionsItemSelected() 定义菜单响应事件
调用item.getItemId()
判断点击的是哪个菜单项。
@Override
public boolean onOptionsItemSelected(MenuItem item) {
swith (item.getItemId()) {
case R.id.add_item:
Toast.makeText(this, "add", Toast.LENGTH_SHORT).show();
break;
case R.id.remoce_item:
Toast.makeText(this, "remove", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
4. 销毁活动
调用 finish()
方法。
(二) 使用Intent
1. 显式Intent
构造方法接收两个参数:( context提供启动活动的上下文,class指定想启动的目标活动 )
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
startActivity(intent);
2. 隐式Intent
指定action和category等信息。action只能指定一个,category可指定多个。
Intent intent = new Intent("com.example.activitytest.ACTION_START");
intent.addCategory("com.example.activitytest.MY_CATEGORY");
startActivity(intent);
3.隐式Intent启动其他程序
// 浏览器
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
//拨号
Intent intent = new Intent(Intent.ACTION_DIAL);
intent.setData(Uro.parse("tel:10086"));
startActivity(intent);
4.向下一个活动传递数据
- 传入:调用
putExtra()
,接收两个参数分别为键值。 - 取出:首先调用
getIntent()
获取Intent,再根据传递的数据类型,调用getStringExtra()
、getIntExtra()
等方法。
//传入
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
Intent.putExtra("extra_data",data);
startActivity(intent);
//取出
Intent intent= getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity", data);
5. 返回数据给上一个活动
- 启动活动:使用
startActivityForResult()
,它接收两个参数 ( Intent, 请求码 )。 - 返回数据:new出一个Intent
putExtra()
放入数据,调用setResult(RESULT_OK, intent)
,最后销毁当前活动。 - 获取数据:重写回调的
onActivityResult()
方法,检查requestCode和resultCode,调用data.getStringExtra()
取出数据。
// 获取数据
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
break;
default:
}
}
(三) 活动的生命周期
四种状态:运行、暂停、停止、销毁。
三种生存期:
- 完整生存期 onCreate() — onDestroy()
- 可见生存期 onStart() — onStop()
- 前台生存期 onResume() — onPause()
程序状态的恢复:
- 保存:重写
onSaveInstanceState()
,调用Bundle的putString()
、putInt()
等方法传入键值保存数据。 - 恢复:
savedInstanceState.getString()
//保存
@Override
protected void onSaveInstanceState(Bundle outstate) {
super.onSaveInstanceState(outState);
String tempData = "Something";
outState.putString("data_key", tempData);
}
//恢复 (onCreate中)
if (savedInstanceState != null) {
String tempData = savedInstanceState.getString("data_key");
Log.d(TAG, tempData);
}
(四) 活动的启动模式
- 在AndroidManifest.xml中修改activity标签的
android:launchMode=""
standard
singleTop
singleTask
singleInstance
二、 Broadcast
(一) 简介
广播的类型:主要分为标准广播和有序广播。
- 标准广播:异步执行,同时接收没有先后顺序,无法截断。
- 有序广播:同步执行,有先后顺序,可被截断。
广播接收器的生命周期:只有十秒左右,如果在 onReceive() 内做超过十秒的事情,就会报ANR(Application No Response) 程序无响应的错误信息。
(二) 接收系统广播
1. 动态注册
新建一个类,让它继承自BroadcastReceiver,并重写父类的 onReceive() 方法。
调用 registerReceiver(receiver实例, intentFileter)
进行注册,最后需要调用 unregisterReveiver(receiver实例)
取消注册。
public class MainActivity extends AppcompatActivity {
private IntentFilter intentFilter;
private NetworkChangeReceiver networkChangeReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intentFileter = new IntentFilter();
intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
networkChangeReceiver = new NetworkChangeReceiver();
registerReceiver(networkChangeReceiver, intentFilter);
}
@Override
protected void onDestroy() {
super.onDestroy();
unregisterReceiver(networkChangeReceiver);
}
class NetworkChangeReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
ConnectivityManager connectionManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE;
NetworkInfo networkInfo = connectionManager.getActiveNetworkInfo();
if(networkInfo != null && networkInfo.isAvailable()) {
Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
}
}
}
}
2. 静态注册
可以让程序在未启动的状态下接收到广播。
新建BroadcastReceiver,在 onReceive() 中写入相应逻辑,并在AndroidManifest.xml中注册,<intent-filter>
标签中添加相应action。
public class BootCompleteReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
}
}
...
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
...>
<receiver
android:name=".BootCompleteReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
(三) 发送自定义广播
1. 发送标准广播
构建Intent对象,把要发送的广播的值传入,调用context的 sendBroadcast(intent)
发送广播。
Intent intent = new intent("com.example.broadcasttest.MY_BROADCAST");
sendBroadcast(intent);
2. 发送有序广播
- 发送广播使用
sendOrderedBroadcast(intent, null)
方法。 - AndroidManifest中通过
android:priority
属性给广播接收器设置优先级,优先级高的先收到广播。 - onReceive() 中调用
abortBroadcast()
可将广播截断。
// 发送广播
Intent intent = new intent("com.example.broadcasttest.MY_BROADCAST");
sendOrderedBroadcast(intent,null);
// 设置优先级
<intent-filter android:priority="100">
<action android:name="com.example.broadcasttest.MY_BROADCAST" />
</intent-filter>
// 截断广播
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_SHORT).show();
abortBroadcast();
}
(四) 使用本地广播
使用本地广播机制发出的广播只能在应用程序内部传递,并且广播接收器也只能接收来自本程序的广播,保证安全性。
借助LocalBroadcastManager对广播进行管理,和动态注册广播几乎一样。
- 获取localBroadcastManager实例:调用
LocalBroadcastManager.getInstance(this)
。 - 发送本地广播:调用
localBroadcastManager.sendBroadcast(intent)
。 - 注册和取消注册广播接收器:新建一个LocalReceiver,调用
localBroadcastManager.registerReceiver(localReceiver, intentFilter)
和localBroadcastManager.unregisterReceiver(localReceiver)
。
注意:本地广播无法通过静态注册方式来接收。
三、 Service
(一) 基本用法
1. 定义一个服务
新建Myservice,重写 onCreate()
、onStartCommand()
和 onDestroy()
三个方法,并在AndroidManifest中注册。
- onCreate():服务创建时调用。
- onStartCommand():每次服务启动时调用,主要处理逻辑写在此处。
- onDestroy():服务销毁时调用,回收不再使用的资源。
public class MyService extends Service {
...
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
2. 启动和停止服务
- 活动中:借助Intent,调用
startService(startIntent)
和stopService(stopIntent)
来启动和停止服务。 - 服务中:任何位置调用
stopSelf()
方法让服务自己停止。
3. 活动和服务进行通信
- 在Service中创建一个专门的Binder对象进行管理,在
onBind()
方法中返回这个实例。 - 在Activity中创建ServiceConnection的匿名类,重写
onServiceConnected()
和onServiceDisconnected
方法,它们分别在活动与服务成功绑定和解除绑定时调用。
- 在
onServiceConnected()
中获得Binder的实例,可以调用其中的任何公共方法。 - 调用
bindservice(Intent, ServiceConnection实例, BIND_AUTO_CREATE)
绑定并自动创建服务。 - 调用
unBindService(ServiceConnection实例)
解除绑定。
- 在
public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder {
public void startDownload() {
Log.d("MyService", "startDownload executed");
}
public int getProgress() {
Log.d("MyService", "getProgress executed");
return 0;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
...
}
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onSeviceConnected(ComponentName name, Ibinder service) {
downloadBinder = (MyService.DownloadBinder) service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
...
Button bindService = (Button) findViewById(R.id.bind_service);
Button unbindService = (Button) findViewById(R.id.unbind_service);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch(v.getId()) {
...
case R.id.bind_service:
Intent bindIntent = new Intent(this, MyService.class);
bindService(bindIntent, connection, BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
default:
break;
}
}
}
(二) 服务的生命周期
Service有两种使用方法:
- 以调用
Context.startService()
启动,以调用Context.stopService()
结束。 - 以调用
Context.bindService()
方法建立,以调用Context.unbindService()
关闭。
(三) 服务的更多技巧
1. 使用前台服务
- 能使服务一直保持运行,并常驻状态栏。
- onCreate()中:构建一个Notification对象后调用
startForeground(通知id, Notification对象)
让服务成为前台服务。
public class MyService extends Service {
...
@Override
public void onCreate() {
super.onCreate();
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
// 获取用于启动Activity的PendingIntent,接收四个参数:上下文、请求码、Intent、flag参数
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("This is content title")
.setContentText("This is content text")
.setWhen(System.currenTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_Launcher))
.setContentIntent(pi)
.bulid();
startForeground(1, notification);
}
...
}
2. 使用IntentService
- 可以简单的创建一个异步的、会自动停止的服务。
- 新建MyIntentService类继承自IntentService:
- 首先提供一个无参的构造函数,并在其内部调用父类的有参构造函数;
- 实现
onHandleIntent()
抽象方法,在其中处理具体逻辑。
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService"); // 调用父类的有参构造函数
}
@Override
protected void onHandleIntent(Intent intent) {
// 处理具体逻辑,这里打印当前线程id
Log.d("MyIntentService", "Thread is" + Thread.currentThread().getId());
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d("MyIntentService", "onDestroy executed");
}
}
四、 Content Provider
待填坑