《第一行代码 ANDROID》学习笔记 ( 只记录碎片知识 )
第二章
1、活动的基本用法
1> 创建活动
package com.example.myapplication;
import ...
public class FirstActivity extends AppCompatActivity {
@override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout); //引入布局
}
}
2> 创建和加载布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayut xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_1" //在XML中定义一个id
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button 1"/>
</LinearLayout>
3> 在 AndroidMainifest 文件中注册
<?xml="1.0",encoding="utf-8"?>
<mainfest xmlns:android="http://schemas.andrid.com/apk/res/android"
package="com.example.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="My Application"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".FirstActivity" //指定具体注册哪一个活动
android:label="This is FirstActivity"> //指定标题栏的内容
//注意:主活动的label会成为启动器中应用程序显示的名称
<intent-filter> //声明主活动
<action android:name="android.intent.action.MAIN"/>
<categroy android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
2、在活动中使用 Toast
package com.example.myapplication;
import ...
public class FirstActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstantState){
super.onCreate(savedInstanceState);
setContentView(R.layout.first_layout);
Button button1 = (Button) findViewById(R.id.button_1);
button_1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Toast.makeText(context:FirstActivity.this,text:"You clicked Button 1",
Toast.LENGTH_SHORT).show();
}
});
}
}
<!--
1、通过 findViewById() 方法获取到在布局文件中定义的元素,得到按钮的实例。findViewById方法返回的是一个View对象,需要向下转型为Button对象。
2、通过调用setOnClickListener()方法为按钮注册一个监听器,点击按钮时就会执行监听器中的onClick方法。
3、通过静态方法makeText创建出一个Toast对象,然后调用show将Toast显示出来。makeText方法中需要3个参数,第一个参数是Context,也就是Toast要求的上下文。第二个参数是Toast显示的文本内容。第三个参数是Toast显示的时长,Toast.LENGTH_SHORT和Toast.LENGTH_LONG。
-->
3、在活动中使用 Menu
res -> menu -> main.xml
// 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>
// FirstActivity
// 重写onCreatOptionMenu方法,通过getMenuInflater方法得到MenuInflater对象,再调用inflate方法给当前活动创建菜单。inflate接受两个参数,第一个参数用来指定我们通过哪一个资源文件来创建菜单,第二个参数用来指定我们的菜单项将添加到哪一个Menu对象当中。
@Override
public boolean onCreatOptionMenu(Menu menu){
getMenuInflater().inflate(R.menu.main,menu);
return true; // 返回true表示允许创建的菜单显示出来,false表示不显示
}
// 重写onOptionItemSelected方法,通过item.getItemId来判断点击的是哪一个菜单项
@Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case R.id.add_item:
Toast.makeText(this,"You clicked Add",Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this,"You clicked Remove",Toast.LENGTH_SHORT).show();\
break;
default:
}
return true;
}
4、销毁一个活动
button1.setOnClickListener(new View.onClickListener(){
@Override
public void onClick(View v){
finish();
}
});
5、使用 Intent 在活动之间穿梭
1> 显式 Intent
//方法一:class跳转
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivity(intent);
//方法二:包名、类名
Intent intent = new Intent();
intent.setClassName(packageContext:this,className:"com.example.mainactivity.SecondActivity");
startActivity(intent);
//方法三:ComponentName
Intent intent = new Intent();
ComponentName cname = new ComponentName(pkg:this,SecondActivity.class);
intent.setComponent(cname);
startActivity(intent);
2> 隐式 Intent
//方法一
Intent intent = new Intent();
intent.setAction("action.nextActivity");
startActivity(intent);
//方法二
Intent intent = new Intent(action:"action.nextActivity");
startActivity(intent);
//每个intent中只能指定一个action,但却能指定多个category
Intent intent = new Intent(action:"action.nextActivity");
intent.addCategory("com.example.application.MY_CATEGORY");
startActivity(intent);
//启动其他程序的活动
//调用浏览器浏览网页
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
startActivity(intent);
}
});
//可以指定当前活动能够响应什么类型的数据 AndroidMainfest.xml
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<data android:schema="http" />
</intent-filter>
</activity>
<!--
android:scheme : 指定数据的协议部分
android:host : 指定数据的主机名部分
android:port : 指定数据的端口部分
android:path : 指定主机名和端口之后的部分,例如:域名//path
android:mimeType : 指定可以处理的数据类型
-->
//显示地理位置
intent.setData(Uri.parse("geo:xian"));
//拨打电话
intent.setData(Uri.parse("tel:10086"));
3> 向下一个活动传递数据
// FirstActivity
// 1、使用显示Intent的方式启动SecondActivity
// 2、通过putExtra方法接收两个参数,第一个参数是键,用来后面从Intent中取值,第二个参数是传递的数据
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String data = "Hello SecondActivity";
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
intent.putExtra("extra_data",data);
startActivity(intent);
}
});
// SecondActivity
// 1、通过getIntent方法获取用来启动SecondActivity的Intent
// 2、调用getStringExtra方法,传入相应的键值,获取传递的数据
// 3、提供很多种数据的传递方法,如getStringExtra、getIntExtra、getBooleanExtra等
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Intent intent = getIntent();
String data = intent.getStringExtra("extra_data");
Log.d("SecondActivity",data);
}
}
4> 返回数据给上一个活动
//FirstActivity
//startActivityForResult方法接收两个参数,第一个参数是Intent,第二个参数是请求码requestCode,其作用是启动活动,但是期望在活动销毁时能返回返回一个结果给上一个活动
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,SecondActivity.class);
startActivityForResult(intent,1);
}
//FirstActivity 重写onActivityResult方法
@override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (request requestCode) {
case 1:
if (resultCode == RESULT_OK) {
String returnedData = data.getStringExtra("data_retrun");
Log.d("FirstActivity",returnedData);
}
break;
default:
}
}
//SecondActivity
// 1、构建一个Intent,这个intent只是用来传递数据,所以不需要指定参数
// 2、调用setResult方法,其接收两个参数,第一个参数用于向上一个活动返回处理结果,一般只使用RESULT_OK或者RESULT_CANCELED两个值,第二个参数则把带有数据的Intent传递回去
public class SecondActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second_layout);
Button button2 = (Button) findViewById(R.id.button_2);
button2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(RESULT_OK,intent);
finish();
}
});
}
}
//SecondActivity
//改写onBackPressed方法,使得当点击back键时也可以返回数据
@Override
public void onBackPressed() {
Intent intent = new Intent();
intent.putExtra("data_return","Hello FirstActivity");
setResult(RESULT_OK,intent);
finish();
}
6、活动的生命周期
1> 返回栈
- Andorid是使用任务(Task)来管理活动的,一个任务就是一组存放在栈里的活动的集合,此栈是返回栈。
- 默认情况下,我们启动一个新的活动,它会在返回栈中入栈,并处于栈顶的位置;每当按下Back键或调用
finish()方法去销毁一个活动时,处于栈顶的活动会出栈,这时前一个入栈的活动就会重新处于栈顶位置。
- 系统总是会显示处于栈顶的活动给用户。
2> 活动状态
- 运行状态 :处于栈顶的活动
- 暂停状态 :不再处于栈顶,却仍然可见的活动
- 停止状态 :不再处于栈顶,且完全不可见的活动
- 销毁状态 :从返回栈中移除的活动
3> Activity类中定义的7个回调方法
- onCreate() : 完成活动的初始化,比如加载布局、绑定事件等
- onStart() : 在活动由不可见变为可见的时候调用
- onResume() : 在活动准备好和用户进行交互时调用,此时的活动一定处于栈顶,并且处于运行态
- onPause() : 系统准备去启动或恢复另一个活动时调用
- onStop() :在活动完全不可见时调用
- onDestory() : 在活动被销毁之前调用
- onRestart() : 活动由停滞状态变为运行状态之前调用
4> 活动的生存期
- 完整生存期 :onCreate() 和 onDestory()
- 可见生存期 :onStart() 和 onStop()
- 前台生存期 :onResume() 和 onPause()
> 活动被回收了怎么办?
- 用户在活动A的基础上启动了活动B,活动A就进入了停止状态,这时由于系统内存不足,将活动A回收掉了,然
后用户按下Back键返回活动A,此时还是会正常显示活动A,只不过这是并不会执行onStart()方法,而是会执
行活动A的onCreate()方法,因为活动A在这种情况下会被重新创建一次。
- 但是如果活动A具有临时数据的话,从活动B返回活动A时,临时数据会丢失。
- Activity中提供了一个onSaveInstanceState()回调方法,此方法可以保证在活动被回收之前一定会被调
用。
7、活动的启动模式
-1- standard 默认模式
系统不会在乎这个活动是否已经返回栈中存在,每次启动都会创建该活动的一个新的实例。
-2- singleTop
在启动活动时如果发现返回栈的栈顶已经是该活动,则认为可以直接使用它,不会再创建新的活动实例。
-3- singleTask
每次启动该活动时系统首先会在返回栈中检查是否存在该活动的实例,如果发现已经存在则直接使用该实例,并把
这个活动之上的所有活动统统出栈,如果没有发现就会创建一个新的活动实例。
-4- singleInstance
会启动一个新的返回栈来管理这个活动 (其实如果singleTask模式指定了不同的taskAffinity,也会启动一个
新的返回栈)。
8、活动的最佳实践
-1- 知晓当前是在哪一个活动
创建一个新类 BaseActivity ,不需要在 AndroidMainifest.xml 中注册,因为不需要显示出来。
// BaseActivity
public class BaseActivity extends AppCompatActivity {
@override
protected void onCreat(Bundle savedInstance) {
super.onCreate(savedInstanceState);
log.d("BaseActivity",getClass().getSimpleName());
}
}
// 使项目中的所有类都继承于 BaseActivity 类,由于 BaseActivity 类继承 AppCompatActivity 类,
所以并不影响项目中其他类的功能。
> 程序运行,进入活动1、2、3,debug显示如下
com.example.activitytest D/BaseActivity: FirstActivity
com.example.activitytest D/BaseActivity: SecondActivity
com.example.activitytest D/BaseActivity: ThirdActivity
-2- 随时随地退出程序
创建一个 ActivityCollector 类作为活动管理器
public class ActivityCollector {
public static List<Activity> activities = new ArrayList<>();
public static void addActivity (Activity activity) {
activities.add(activity);
}
public static void removeActivity (Activity activity) {
activities.remove(activity);
}
public static void finishAll() {
for(Acivity activity : activities) {
if(!activity.isFinishing()) {
activity.finish();
}
}
activities.clear();
}
}
// BaseActivity
public void BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d("BaseActivity",getClass().getSimpleName());
ActivityCollector.addActivity(this);
}
@Override
protected void onDestory() {
super.onDestory();
ActivityCollector.removeActivity(this);
}
}
-3- 启动活动的最佳写法
Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
intent.putExtra("param1","data1");
intent.putExtra("param2","data2");
startActivity(intent);
> 对上述代码进行修改
public class SecondActivity extends BaseActivity {
public static void actionStart(Context context,String data1,String data2) {
Intent intent = new Intent(context,SecondActivity.class);
intent.putExtra("param1","data1");
intent.putExtra("param2","data2");
context.startActivity(intent);
}
...
}
> 启动活动
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SecondActivity.actionStart(FirstActivity.this,"data1","data2");
}
});