下载Android stdio,直接在官网下载。
新建一个project。
在activity_main.xml文件中输入
<Button
android:id="@+id/button1"//新增一个名为“button”的资源id
android:text="Button1"//按钮上的文本
android:layout_width="match_parent"//layout_width就是父布局允许view所占的宽度
android:layout_height="wrap_content"//高度
tools:ignore="MissingConstraints" />
在前面
match_parent表示让当前控件的大小和父布局的大小一样,也就是由父布局来决定当前控件的大小
wrap_content表示让当前的控件大小能够刚好包含里面的内容,也就是由控件内容决定当前控件的大小
此时会发现按钮上的文本“botton1”是全大写字母“BOTTON1”,以下的修改方法:
找到AndroidManifest.xml找到
android:theme="@style/AppTheme">
按Ctrl键左键进入主题
在前面添加一个项目
<item name="android:textAllCaps">false</item>//把文本全部大写这个功能关闭
然后回到“MainActivity.java”源文件中添加对应的对象button1
private Button button1;
这里调用了setContentView()方法来给当前的活动加载一个布局,此时创建的activity_main.xml布局的资源id会添加到R文件中,只需要调用R.layout.activity_main就可以得到activity_main.xml布局的id,然后将这个值传入setContentView()方法即可。
此时button类所在的包将会自动导入进来,如图
接下来初始化视图
/**
* 初始化视图
*/
public void initView() {
button1 = findViewById(R.id.button1);
}
此时打开模拟器会出现按钮,按钮可以点击但没有任何反应。
另外补充:
Androidmanifest.xml就是用来写App的必要的配置。可Androidmanifest.xml中的icon、label、theme等处在res文件夹中分别修改APP的图标、标签(名称)和主题等等。
/**
* 初始化视图
*/
public void initView() {
button1 = findViewById(R.id.button1);
//为按钮添加监听器
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//onClick方法会在button1这个按钮按下时自动被调用执行
// Toast.makeText(MainActivity.this, "Hello你好呀", Toast.LENGTH_LONG).show();
//显示Intent(意图)
// Intent intent = new Intent(MainActivity.this, SecondActivity.class);
// startActivity(intent);
//隐式Intent
// Intent intent = new Intent("com.androidstudy.activitytest.START_ACTION");
// startActivity(intent);
/*
//通过隐式Intent调用系统应用
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
// intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:12345678910"));//拨号
//intent.setAction("Android.settings.SETTINGS"); //打开设置窗口
startActivity(intent);
*/
Intent intent = new Intent(MainActivity.this, SecondActivity.class);
/*
intent.putExtra("Data","Hello SecondActivity");
startActivity(intent); //传递数据
*/
startActivityForResult(intent,1);
}
});
}
打出Toast在Android stdio强大的功能支持下就会出现如图
其中MainActivity.this表示的意思context(上下文)
类名.this 这种语法在什么情况下会出现呢?
一句话:内部类需要用到外部类的成员变量或方法。
附加说明:如果重名则必须“类名.this”指定那个类的成员变量或方法,如果没有重名则该变量可以指定所属类也可以不指定所属类。
其中text表示显示文本
其中第三个表示显示时长
首先在res文件夹里新建一个名为“menu”的文件夹,一定要取为“menu”。在该文件夹中新建一个menu resource file。
在menu.xml文件中在前面添加这两行
<item android:id="@+id/add_item" android:title="Add"/>
<item android:id="@+id/remove_item" android:title="Remove"/>
在MainActivity中创建一个onCreateOptionsMenu()方法
OptionsMenu的意思是选项菜单,还有其他类型的菜单:上下文菜单
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu,menu);
return super.onCreateOptionsMenu(menu);
}
getMenuInflater().inflate(R.menu.menu,menu);这一行中通过getMenuInflater()方法能够得到MenuInflate对象,inflate()方法接收两个参数,第一个参数用于指定我们通过哪一个资源文件来创建菜单;第二个参数用于指定我们的菜单项将添加到哪一个Menu对象当中。
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.add_item:
Toast.makeText(this, "Add_Item clicked", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "Remove_Item clicked", Toast.LENGTH_SHORT).show();
break;
}
return super.onOptionsItemSelected(item);
}
(打开新的activity)
在mainactivity.java所在文件夹中新建一个activity
在activity_second.xml中添加一个按钮
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondActivity">
<Button
android:id="@+id/button2"
android:text="Button2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
现在的需求是点击MainActivity的按钮能从MainActivity切换到secondActivity上。
//显式Intent(意图)
Intent intent = new Intent(MainActivity.this,SecondActivity.class);
startActivity(intent);
//隐式Intent
// Intent intent = new Intent("com.androidstudy.activitytest.START_ACTION");//这么长的东西其实是自定义的,可以任意地改
// startActivity(intent);
//通过隐式Intent调用系统应用
Intent intent = new Intent();
intent.setAction(Intent.ACTION_CALL);
// intent.setAction(Intent.ACTION_DIAL);//DIAL是转到电话输入了对应号码的界面但为拨号
intent.setData(Uri.parse("tel:12345678910"));//拨号
//intent.setAction("Android.settings.SETTINGS"); //打开设置窗口
//intent.setAction("com.android.contacts.action.LIST_CONTACTS")//打开联系人窗口
startActivity(intent);
此时会发现APP打不开,因为在手机中该APP没有申请打电话的权限
要在AndroidManifest.xml中写这一句
<uses-permission android:name="android.permission.CALL_PHONE"/>
若要实现其他更多的功能,可以在android API文档中查找
https://developer.android.google.cn/guide
intent.putExtra("Data","Hello SecondActivity");
startActivity(intent); //传递数据
其中“Data”表示传递数据的名称,“Hello SecondActivity”表示传递的数据
在SecondActivity.java文件中写
Intent intent = getIntent();
String data = intent.getStringExtra("Data");
Log.d("SecondActivity", data);
initView();
startActivityForResult(intent,1);//第二个参数是requestCode
其中,requestCode表示:如果> = 0,当Activity结束时requestCode将归还在onActivityResult()中。以便确定返回的数据是从哪个Activity中返回,用来标识目标activity。
在SecondActivity中写
/*
初始化窗口
*/
public void initView(){
button2 = findViewById(R.id.button2);
button2.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View view){
Intent intent = new Intent();
intent.putExtra("data_return","Hello MainActivity");
setResult(RESULT_OK,intent);
finish();//关闭窗口
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
switch (resultCode) {
case 1:
if (resultCode == RESULT_OK) {
String resultData = data.getStringExtra("data_return");
Log.d("MainActivity", resultData);
}
break;
}
一个任务就是一组存放在栈里的活动的集合,这个栈被称为 返回栈(Back Stack) 。
栈是一种后进先出的数据结构。
当启动一个新活动,便会在返回栈中入栈,并处于栈顶的位置。
当按下Back键或者finish()方法销毁一个活动,处于栈顶位置的活动会出栈,前一个入栈的活动重新处于栈顶的位置。
系统总是显示处于栈顶的活动给用户。
(1)运行状态:一个活动位于返回栈的栈顶,该活动便处于运行状态。
系统不愿意收回运行状态的活动,会导致用户体验很差。
(2)暂停状态:一个活动不再处于栈顶,但依然可见时,该活动便处于暂停状态。
系统也不愿意回收这类活动,因为它还是可见的,回收可见的东西会影响用户的体验。只有内存极低的情况下,系统会考虑回收这类活动。
(3)停止状态:一个活动不再处于栈顶位置,并且完全不可见时,该活动便处于停止状态。
系统会为这类活动保存相应的状态和成员变量,但是并不可靠,当其他地方需要内存时,该状态的活动很可能被系统回收。
(4)销毁状态:一个活动从返回栈中被移除,便处于销毁状态。
系统倾向于回收这类活动,保证手机的内存充足。
Activity类定义了7个回调方法。
(1)onCreate():在活动第一次被创建的时候调用。在这个方法中完成活动的初始化操作,例如加载布局、绑定事件等
(2)onStart():在活动由不可见变成可见的时候调用。
(3)onResume():在活动准备好和用户进行交互的时候调用。此时活动位于返回栈的栈顶,并且处于运行状态。
(4)onPause():在系统准备去启动或者恢复另一个活动的时候调用。在该方法中将一些销毁CPU的资源释放掉,保存关键数据。该方法执行速度一定要快,不然会影响栈顶活动的使用
(5)onStop():在方法完全不可见的时候调用。注意onStop()与onPause()的区别。
(6)onDestroy():在活动被销毁之前调用。
(7)onRestart():在活动由停止状态变为运行状态前调用。
以上七种方法中除了onRestart()方法,其他都是两两相对的,从而又可以将活动分为3种生存期
(1)完整生存期 活动在onCreate()方法和onDestroy()方法之间经历的,就是完整生存期。一般情况下,活动会在onCreate()方法中完成各种初始化操作,而在onDestory()方法中完成释放内存的操作
(2)可见生存期 活动在onStart()方法和onStop()方法之间经历的 就是可见生存期。在可见生存期内,活动对于用户总是可见的,即便可能无法与用户进行交互。
(3)前台生存期 活动在onResume()方法和onPasue()方法之间经历的就是前台生存期。在前台生存期内,活动总处于运行状态,此时活动是可以和用户交互的。
新建一个APP,命名为ActivityRecycleTest,在MainActivity.java文件同目录下新建一个activity,命名为NormalActivity
在activity_normal.xml中写
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="This is a normal activity"
tools:ignore="MissingConstraints" />
那句tools:ignore="MissingConstraints"是系统给的,不知道是什么意思,书里是没有这句的。
然后再新建一个activity,命名为DialogActivity
在activity_main.xml中写
<Button
android:id="@+id/btn_start_normal_activity"
android:text="StartNormalActivity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/btn_start_dialog_activity"
android:text="StartDialogActivity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints" />
定义两个按钮,但很奇怪,布局只显示一个按钮,如图
解决方法:把布局改成LinearLayout,方向orientation改成vertical(垂直)
如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="visible"
tools:context=".MainActivity"
tools:visibility="visible">
<Button
android:id="@+id/btn_start_normal_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="StartNormalActivity"
tools:ignore="MissingConstraints" />
<Button
android:id="@+id/btn_start_dialog_activity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="StartDialogActivity"
tools:ignore="MissingConstraints" />
</LinearLayout>
然后再MainActivity中声明这两个类
private Button btnStartNormalActivity,btnStartDialogActivity;
在MainActivity中,这么写:
public class MainActivity extends AppCompatActivity {
private Button btnStartNormalActivity,btnStartDialogActivity;
private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
Log.d(TAG,"onCreate()");
}
@Override
protected void onStart() {
super.onStart();
Log.d(TAG,"onStart()");
}
@Override
protected void onResume() {
super.onResume();
Log.d(TAG,"onResume()");
}
@Override
protected void onPause() {
super.onPause();
Log.d(TAG,"onPause()");
}
@Override
protected void onStop() {
super.onStop();
Log.d(TAG,"onStop()");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.d(TAG,"onDestroy()");
}
@Override
protected void onRestart() {
super.onRestart();
Log.d(TAG,"onRestart()");
}
/**
* 初始化窗口
*/
public void initView(){
btnStartNormalActivity = findViewById(R.id.btn_start_normal_activity);
btnStartDialogActivity = findViewById(R.id.btn_start_dialog_activity);
btnStartNormalActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,NormalActivity.class);
startActivity(intent);
}
});
btnStartDialogActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(MainActivity.this,DialogActivity.class);
startActivity(intent);
}
});
}
}
接下来要把DialogActivity改成对话框的形式
在Androidmanifest.xml中将
<activity android:name=".DialogActivity"></activity>
改成
<activity android:name=".DialogActivity"
android:theme="@style/Theme.AppCompat.Dialog"></activity>
最后开始运行,不点击按钮或点击对应按钮就可以在logcat中看到生命周期过程
四种启动模式:
standard
singleTop
singleTask
singleInstance
修改活动的启动模式,通过xml活动中的”android:launchMode”修改,Android通过返回栈来管理活动。
新建一个project,命名为LaunchModeTest。
将MainActivity.java改名为FirstActivity
在Activitymanifest.xml中将
<activity android:name=".FirstActivity">
更改为
<activity android:name=".FirstActivity" android:launchMode="standard">
在FirstActivity.xml中生成一个按钮
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".FirstActivity">
<Button
android:id="@+id/button1"
android:text="Button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
FirstActivity.java中这么写
package com.example.launchmodetest;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
public class FirstActivity extends AppCompatActivity {
private Button button1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d("FirstActivity",this.toString());
initView();
}
private void initView() {
button1 = findViewById(R.id.button1);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(FirstActivity.this,FirstActivity.class);
startActivity(intent);
}
});
}
}
运行后,点击按钮会发现跳出新的重复的界面,点击多次就多次跳出。
如果把在Activitymanifest中将模式改成singleTop就不会重复跳出。
略