文章目录
4.1 Activity生命周期
4.1.1 生命周期状态
Activity的生命周期代表的是Activity从创建到销毁的过程,大致分为五种状态
- 启动状态
- 运行状态:此状态的Activity在界面的最前端,是可见的有焦点的,可以与用户进行交互,此外当Activity处于运行状态的时候,Activity会尽量保持这种状态,即使出现内存不足的情况,也会先摧毁栈底的Activity来确保当前的Activity正常运行
- 暂停状态:某些情况,Activity可见,但是无法与其交互,例如Activity上覆盖了一个透明或者非全屏的界面
- 停止状态:当Activity完全不可见的时候,就处于停止状态,如果内存不足,就会被销毁
- 销毁状态:被清出内存
4.1.2 生命周期方法
Activity的回调方法如下
- onCreat():创建Activity时调用,经常用于初始化设置
- onStart():即将可见时调用
- onResume():获取焦点时调用
- onPause():当前Activity被其他Activity覆盖或者锁屏的时候调用
- onStop():Activity对用户不可见的时候调用
- onRestart():Activity从停止状态到启动状态的时候调用
- onDestroy():销毁Activity
注意点:
当手机进行横竖屏切换的时候,Activity会默认先销毁再创建,因此竖屏状态下在Activity输入的信息会在切换横竖屏后清除,如果不希望切换的时候销毁Activity,可以通过configChanges属性进行设置
AndroidManifest.xml
<activity
android:name=".MainActivity"
android:configChanges="orientation|keyboardHidden"></activity>
4.2 Activity的创建,配置,启动和关闭
###4.2.1 创建步骤
之后填写Activity名称,界面名,包名即可完成创建
需要在AndroidManifest.xml中添加声明Activity才能使用
(需要包名一致)
<activity android:name=".SecondActivity">
</activity>
###4.2.3启动和关闭Activity
启动Activity
创建Activity后可以通过startActivity()来启动创建的Activity
startActivity(new Intent(TestActivity.this,SecondActivity.class));//跳转到相应Activity
参数intent为Android各组件之间通信的桥梁,一个Activity通过intent来表达自己的意图,创建Intent对象的时候指定想要启动的Activity
关闭Activity
public void finish();
若想要关闭当前的Activity可以使用finish()方法,放到Activity的相应事件方法中即可
4.3 Intent与IntentFilter
4.3.1 Intent
Intent是意图,是程序中各个组件进行交互的一种重要的方式,不仅可以指定当前组件要执行的动作,还可以在不同组件之间进行数据传递,一般用于启动Activity和Service以及发送广播,根据开启的目标组件不同,Intent分为两种类型,显式的Intent和隐式的Intent
显式Intent
显示的Intent直接指向目标组件,实例代码如下
Intent intent = new Intent(this,MainActivity.class);
startActivity(intent);
第一个参数表示当前的Activity第二个参数代表的是需要跳转的Activity
隐式Intent
顾名思义,不会明确指出目标组件,被广泛的用于应用程序之间,用于消息传递,Android会使用IntentFilter匹配相应的组件,属性有三个
- action属性:表示Intent对象要完成的动作
- data属性:表示Intent对象要传递的数据
- category属性:表示为action属性添加额外的信息
例如需要在project1中的MainActivity开启project2中的SecondActivity
-
在project2中AndroidManifest.xml中设置action属性和category属性
<intent_filter> <action android:name="cn.itcase.START_ACTIVITY"/> <category android:name="android.intent.category.DEFAULT"/> </intent_filter>
-
在project1中开启project2中相应活动
Intent intent = new Intent(); intent.setAction("cn.itcase.START_ACTIVITY"); startActivity(intent);
4.3.2 IntentFilter
当系统发送一个隐式的Intent的时候,Android会将它与程序中的每一个过滤器中的组件进行匹配,匹配的属性有action,data,category,只有这三个组件都匹配成功才能唤醒相应的组件
action匹配规则
在清单文件中可以设置多个action,但必须要有一个action,否则无法跳转,当使用隐式的Intent激活组件的时候,只需要携带其中一个action就可以完成匹配
data匹配规则
data属性用来指定数据的uri或者数据MIME类型,他的值通常与Intent和action属性有关联
<intent-filter>
<data android:mimeType = "video/mpeg" android:scheme = "http...."/>
<data android:mimeType = "audio/mpeg" android:scheme = "http...."/>
</intent-filter>
MIME类型可以表示image/ipeg、video等媒体类型
和action一样,只要匹配其中一个data就算匹配成功
category属性匹配规则
可以声明category属性,也可以不声明
<intent_filter>
<category android:name="android.intent.category.DEFAULT"/>
</intent_filter>
Intent携带的category属性必须全部与intentfilter中的某些个匹配才算匹配成功,托Intent中没有携带category,那么它可以和任意的category属性匹配
4.4 Activity之间的跳转
4.4.1 Activity之间的数据传递
Intent可以在界面跳转的过程中传递数据,使用Intent传递数据有两种方式
-
使用Intent的putExtra()方法传递数据
putExtra有很多的重载方法,用于不同的数据类型,第一个参数表示传递的数据名称,第二个参数表示的是传递的数据信息
通过putExtra()方法将传递的数据存储在Intent对象中后,如果先要获取数据,可以通过getXxxExtra()方法实现
//MainActivity Intent intent = new Intent(); intent.setClass(MainActivity.this,SecondActivity.class);//设置跳转的Activity intent.putExtra("student_name","张三"); intent.putExtra("age",16); startActivity(intent); //secondActivity Intent intent = getIntent(); String name = intent.getStringExtra("student_name"); int age = intent.getIntExtra("age",0);
-
使用Bundle类传递数据
Bundle类与Map接口比较类似,通过键值对的形式保存数据
Intent intent = new Intent(); intent.setClass(MainActivity.this,SecondActivity.class);//设置跳转的Activity Bundle bundle = new Bundle(); bundle.putString("student_name","小明"); intent.putExtras(bundle); startActivity(intent);
Bundle bundle = getIntent().getExtras(); String name = bundle.getString("student_name");
4.4.2 Activity中的数据回传
有时候启动某个界面需要从该界面回传某些数据Android提供了某些方法,用于Activity之间的数据回传
startActivityForResult()方法
Activity被销毁的时候,会从销毁的Activity中返回数据
startActivityFroResult(Intent intent,int requestCode)
第一个参数是意图对象,第二个参数是请求码,用来表示请求的来源
setResult方法
用于携带数据回传
setResult(int resultCode,Intent intent)
第一个参数表示返回码,用于标识返回的数据来自哪一个Activity,第二个参数用于携带数据并回传到上一个界面
onActivityResult()方法
用于接收回传的数据
onActivityResult(int requestCode,int resultCode,Intent data)
第一个参数表示请求码,第二个参数表示回传码,第二个参数表示回传的数据,程序会根据requestCode和resultCode来识别数据的来源
应用举例
MainActivity的Button1进入SecondActivity,SecondActivity的Button2点击后回传数据,并关闭SecondActivity
注:startActivityForResult()方法似乎已经被弃用,我编译运行后点击Button1会闪退(Android Q)
MainActivity
public class MainActivity extends AppCompatActivity {
private Button mbtn_1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mbtn_1 = findViewById(R.id.bt_1);
mbtn_1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startActivityForResult(new Intent(MainActivity.this,TestActivity.class),1);//打开Activity
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {//重写该方法,用于显示收到的数据
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 1 && resultCode == 2)
{
String getdata = data.getStringExtra("data");
Toast.makeText(MainActivity.this,getdata,Toast.LENGTH_LONG).show();//显示回传数据
}
}
}
SecondActivity
public class SecondActivity extends Activity {
Bundle bundle = getIntent().getExtras();
String name = bundle.getString("student_name");
}
4.5 任务栈和启动模式
4.5.1 Android中的任务栈
Android的任务栈是一种用来存放Activity的一种容器,先进后出,用户操作二点Activity永远都是栈顶的Activity
4.5.2 Activity的启动模式
standard模式
这种模式是Activity放入默认启动模式,后启动的Activity位于栈顶,每次启动一个Activity就会在栈顶创建一个新的实例
singleTop模式
standard模式启动一个在栈顶的Activity仍需要创建新的实例,而不能直接复用之前的Activity实例,在这种情况下,使用这种模式更为合理,该模式会检测要启动的Activity是不是位于栈顶,如果是复用该Activity,否则创建新的实例
singleTask模式
singleTake模式会判断要启动的Activity是否在栈中,如果是,直接启动,并将其上面的实例弹出栈,实际开发中,浏览器主页经常采用这种方式
singleInstance模式
指定这种模式的Activity会启动一个新的任务栈来管理Activity实例,无论从哪个任务栈启动该Activity,该Activity的实例在整个系统中只会有一个,Android的桌面就是运用的这种模式
启动singleInstance模式的Activity分为两种情况,一是没有Activity实例就会创建一个实例压入栈中,另外一种就是有Activity实例,就会把Activity存在的任务栈转移到前台,实际开发中来电界面就是用的这种模式
4.6 使用fragment
随着移动设备的普及,用平板电脑等大屏设备的人 越来越多,为了兼顾到手机和平板电脑的开发,就产生了fragment,好像平板常用的侧边栏就是用的这个
4.6.1 Fragment简介
Fragment(碎片)是一种嵌入到Activity中的ui片段,可以用来描述Activity中的一部分布局,如果Activity中控件较多,比较复杂,我们就可以用到这个把屏幕划分成几个区域,进行模块化管理
一个Activity可以包含多个Fragment,一个Frament也可以在多个Activity中使用,如果在Activity中有多个相同的业务模块,则可以复用Fragment
4.6.2 Fragment的生命周期
Activity生命周期有五种状态,Fragment的生命周期也有五种状态,因为Fragment嵌入在Activity中,因此其生命周期受Activity的影响
Fragment的生命周期比Activity的生命周期多几个方法
- onAttach():Fragment和Activity建立关系的时候用
- onCreateView():Fragment创建视图(加载布局)的时候使用
- onActivityCreate():Fragment相关联的Activity已经创建完成的时候调用
- onDestroyView():Fragment关联的视图被移除的时候调用
- onDetach():Fragment和Activity解除关联的时候调用
4.6.3 创建Fragment
与Activity类似,创建Fragment时必须创建一个类继承Fragment
public class NewListFragment extends Fragment
{
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v =inflater.inflate(R.layout.fragment,container,false);//动态加载布局文件
return v;
}
}
4.6.4 在Activity中添加Fragment
fragment创建完成后不能单独使用,需要将Fragment中添加到Activity中,添加Fragment有两种方式
布局文件中添加Fragment
添加的时候必须指定name属性,属性值为fragment的全路径
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/newslist"
android:name="cn.itcast.myapplication5.NewListFragment"/>
在Activity中动态加载Fragment
具体步骤如下
- 创建Fragment对象
- 获取FragmentManner(Fragment管理器)的实例
- 开启FragmentTransaction(事务)
- 向Activity的布局容器(一般为FrameLayout)中添加Fragment
- 通过commit()方法提交事务
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NewListFragment fragment = new NewListFragment();
FragmentManager fm = getFragmentManager();//获取实例
FragmentTransaction beginTransaction = fm.beginTransaction();
beginTransaction.replace(R.id.newslist,fragment);//添加Fragment
beginTransaction.commit();//提交事务
}
}
注:此种方法很多方法已被删除,且较为复杂
4.6.5 实战演练-仿美团外卖订单
注:仅参考,很多方法不兼容,书P98
演示图
包含顶部导航栏,左侧菜单栏,右侧的菜单列表
搭建菜单界面布局
添加样式-----themes.xml
<style name="tvNavigationBarStyle">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_marginLeft">25dp</item>
<item name="android:layout_marginTop">4dp</item>
<item name="android:textSize">16sp</item>
</style>
<style name="tvLeftStyle">
<item name="android:layout_width">100dp</item>
<item name="android:layout_height">40dp</item>
<item name="android:gravity">center</item>
<item name="android:textColor">@color/dark_gray</item>
<item name="android:textSize">12sp</item>
</style>
添加颜色-----colors.xml
<color name="gray">#F7F8F9</color>
<color name="dark_gray">#626262</color>
接下来是添加各种界面布局
activity_main.xml
<?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="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_marginBottom="4dp"
android:background="@color/gray"
android:gravity="center_vertical">
<TextView
android:id="@+id/tv_order"
style="@style/tvNavigationBarStyle"
android:text="点菜"
android:textColor="@android:color/black" />
<TextView
android:id="@+id/tv_discuss"
style="@style/tvNavigationBarStyle"
android:layout_toRightOf="@id/tv_order"
android:text="评价"
android:textColor="@color/dark_gray" />
<TextView
android:id="@+id/tv_business"
style="@style/tvNavigationBarStyle"
android:layout_toRightOf="@id/tv_discuss"
android:text="商家"
android:textColor="@color/dark_gray" />
<TextView
android:layout_width="70dp"
android:layout_height="30dp"
android:layout_alignParentRight="true"
android:layout_marginRight="15dp"
android:gravity="center"
android:text="好友拼单"
android:textColor="#ef842c"
android:textSize="12sp" />
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:id="@+id/left"
android:name="cn.itcast.myapplication5.LeftFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@layout/left_layout" />
<fragment
android:id="@+id/right"
android:name="cn.itcast.myapplication5.RightFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="3"
tools:layout="@layout/right_layout" />
</LinearLayout>
</LinearLayout>
left_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f7f8f9"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/tv_recommend"
style="@style/tvLeftStyle"
android:text="推荐"
android:background="@android:color/white"/>
<TextView
android:id="@+id/tv_must_buy"
style="@style/tvLeftStyle"
android:text="进店必买" />
</LinearLayout>
right_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical">
<ListView
android:id="@+id/lv_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:divider="@null"/>
</LinearLayout>
list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="4dp">
<ImageView
android:id="@+id/iv_img"
android:layout_width="70dp"
android:layout_height="70dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:orientation="vertical">
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:textColor="@android:color/black"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_sale"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#868788"
android:textSize="12sp" />
<TextView
android:id="@+id/tv_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:textColor="#e85b4d"
android:textSize="12sp" />
</LinearLayout>
</LinearLayout>
至此界面已经搭好
实现菜单界面功能
FoodBean.java
package cn.itcast.myapplication5;
import java.io.Serializable;
public class FoodBean implements Serializable
{
private static final long serialVersionUID = 1L;
private String name;
private String sales;//菜品月售信息
private String price;
private int img;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSales() {
return sales;
}
public void setSales(String sales) {
this.sales = sales;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
public int getImg() {
return img;
}
public void setImg(int img) {
this.img = img;
}
}
LeftFragment.java
package cn.itcast.myapplication5;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
public class LeftFragment extends Fragment
{
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.left_layout,container,false);
return view;
}
@Override
public void onPause() {
super.onPause();
}
}
RightAdapter.java
package cn.itcast.myapplication5;
import android.content.Context;
import android.telephony.PhoneNumberUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class RightAdapter extends BaseAdapter
{
private Context context;
private List<FoodBean> list;
public RightAdapter(Context context,List<FoodBean> list)
{
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder holder =null;
if(view == null)
{
view = View.inflate(context,R.layout.list_item,null);
holder = new ViewHolder();
holder.tv_name = view.findViewById(R.id.tv_name);
holder.tv_sale = view.findViewById(R.id.tv_sale);
holder.tv_price = view.findViewById(R.id.tv_price);
holder.iv_img = view.findViewById(R.id.iv_img);
view.setTag(holder);
}
else
{
holder = (ViewHolder) view.getTag();//老对象
}
FoodBean bean =list.get(i);
holder.tv_name.setText(bean.getName());
holder.tv_sale.setText(bean.getSales());
holder.tv_price.setText(bean.getPrice());
holder.iv_img.setBackgroundResource(bean.getImg());
return view;
}
class ViewHolder
{
TextView tv_name,tv_sale,tv_price;
ImageView iv_img;
}
}
RightFragment.java
package cn.itcast.myapplication5;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import java.io.Serializable;
import java.util.FormatFlagsConversionMismatchException;
import java.util.List;
public class RightFragment extends Fragment
{
private ListView lv_list;
public RightFragment(){}
public RightFragment getInstance(List<FoodBean>list)
{
RightFragment rightFragment = new RightFragment();
Bundle bundle = new Bundle();
bundle.putSerializable("list",(Serializable) list);
rightFragment.setArguments(bundle);
return rightFragment;
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.right_layout,container,false);
lv_list = view.findViewById(R.id.lv_list);
if(getArguments()!=null)
{
List<FoodBean> list = (List<FoodBean>) getArguments().getSerializable("list");
RightAdapter adapter = new RightAdapter(getActivity(),list);
lv_list.setAdapter(adapter);
}
return view;
}
}
MainActivity.java
package cn.itcast.myapplication5;
import static java.nio.file.Paths.get;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private FragmentManager fragmentManager;
private FragmentTransaction fragmentTransaction;
private LeftFragment leftFragment;
private TextView tv_recommend,tv_must_buy;
private RightFragment rightFragment;
private String[] name1 = {"爆款为辐i刚好我i防刮我ui","豪华双人套餐","热销"};
private String[] sales1 = {"月销售200","月收ufiu","ef"};
private String[] prices1 = {"23","24","25"};
private int[] imgs1 = {R.drawable.a,R.drawable.b,R.drawable.c};
private String[] name2 = {"爆款为辐i刚好我i防刮我ui","豪华双人套餐","热销"};
private String[] sales2 = {"月销售200","月收ufiu","ef"};
private String[] prices2 = {"23","24","25"};
private int[] imgs2 = {R.drawable.a,R.drawable.b,R.drawable.c};
private Map<String, List<FoodBean>> map;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setData();
init();
clickEvent();
}
private void init()
{
fragmentManager = getFragmentManager();//..
LeftFragment = (LeftFragment) fragmentManager.findFragmentById(R.id.left);
tv_recommend = leftFragment.getView().findViewById(R.id.tv_recommend);
tv_must_buy = leftFragment.getView().findViewById(R.id.tv_must_buy);
}
private void setData()
{
map=new HashMap<>();
List<FoodBean> list1 = new ArrayList<>();
List<FoodBean> list2 = new ArrayList<>();
for(int i=0;i<name1.length;i++)
{
FoodBean bean = new FoodBean();
bean.setName(name1[i]);
bean.setSales(sales1[i]);
bean.setPrice(prices1[i]);
bean.setImg(imgs1[i]);
list1.add(bean);
}
map.put("1",list1);
for(int i=0;i<name2.length;i++)
{
FoodBean bean = new FoodBean();
bean.setName(name2[i]);
bean.setSales(sales2[i]);
bean.setPrice(prices2[i]);
bean.setImg(imgs2[i]);
list1.add(bean);
}
map.put("2",list2);
}
private void clickEvent()
{
tv_recommend.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switchData(map.get("2"));
tv_must_buy.setBackgroundResource(R.color.gray);
}
});
switchData(map.get("1"));
}
public void switchData(List<FoodBean>list)
{
fragmentManager = getFragmentManager();
FragmentTransaction = fragmentManager.beginTransaction();
rightFragment = new RightFragment().getInstance(list);
fragmentTransaction.replace(R.id.right,rightFragment);
fragmentTransaction.commit();
}
}