第四章 不可不会的Activity和Fragment【Android基础学习】
  • 前言
  • 版权
  • 推荐
  • 开源
  • 第四章 不可不会的Activity和Fragment
  • 4-1-1 Activity创建三部曲
  • 4-1-2 Activity的生命周期
  • 4-1-3 Activity的跳转和数据传递
  • 4-1-4 Activity的4种启动模式
  • 4-2-1 Fragment详解(一)
  • 4-2-2 Fragment详解(二)
  • 4-2-3 Fragment详解(三)
  • 4-2-4 Fragment详解(四)
  • 最后


前言


推荐

 【天哥】Android开发视频教程最新版 Android Studio开发

图片资源来自:
  https://github.com/jinjungle/skypan-yes-code

开源

日星月云 / 安卓基础学习 https://gitee.com/jsss-1/android-basic-learningjsss-1 / android-basic-learning https://github.com/jsss-1/android-basic-learning

第四章 不可不会的Activity和Fragment

这章的界面LifeCycle、Jump、Fragment在UI界面的GridView和RecyclerView中间

第四章 不可不会的Activity和Fragment【Android基础学习】_android

4-1-1 Activity创建三部曲

  1. 新建类继承Activity或其子类
  2. 在AndroidManifest中声明
  3. 创建layout并在Activity的onCreate中设置

TestActivity
activity_test.xml

AndroidManifest.xml设置Activity属性

  • android:theme=“test” 标签
  • android:theme="@style/Theme.AppCompat.Light.NoActionBar"无,可以application中设置
  • android:screenOrientation=“portrait” 竖屏显示
  • android:launchMode=""启动模式
  • intent-filter设置启动Activity
<activity
            android:name=".MainActivity"
            android:exported="true"
            android:theme="test"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar"
            android:screenOrientation="portrait"
            android:launchMode="">  
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.

4-1-2 Activity的生命周期

第四章 不可不会的Activity和Fragment【Android基础学习】_学习_02


LifeCycleActivity

启动
----onCreate----
----onStart----
----onResume----
  • 1.
  • 2.
  • 3.
  • 4.
退出
----onPause----
----onStop----
----onDestroy----
  • 1.
  • 2.
  • 3.
  • 4.
退到后台
----onPause----
----onStop----
  • 1.
  • 2.
  • 3.
切回前台
----onRestart----
----onStart----
----onResume----
  • 1.
  • 2.
  • 3.
  • 4.
最常用
启动:onCreate
切到后台:onPause
切回前台:onResume
退出:onDestroy
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

4-1-3 Activity的跳转和数据传递

  • 显式跳转和隐式跳转
  • Activity之间的数据传递
  • startActivityForResult:启动Activity,结束后返回结果

AActivity
BActivity
activity_a.xml
activity_b.xml

4-1-4 Activity的4种启动模式

Activity的android:launchMode属性

  • standard:标准模式,默认
  • singleTop:Task栈顶复用模式
  • singleTask:Task栈内复用模式
  • singleInstance:全局单例模式

standard

Activity是由任务栈管理的,每启动一个Activity,就会被放入栈中,按返回键,就会从栈顶移除一个Activity。

standard是默认的启动模式,即标准模式。每启动一个Activity,都会创建一个新的实例。

taskid:任务栈
hash:实例
默认的栈名称:包名
可以通过android:taskAffinity=".asdfghjkdfghj",设置栈名称,必须前面有个.

设置android:launchMode为standard

<activity
            android:name=".jump.AActivity"
            android:label="A"
            android:launchMode="standard"
            android:exported="false" />
        <activity
            android:name=".jump.BActivity"
            android:label="B"
            android:launchMode="standard"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.test.BActivity" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

测试:在A中点击跳转到A
现象:创建了不同的实例

//进入A
2024-06-08 19:08:08.644 10434-10434 AActivity               com.example.helloworld               D  ----onCreate----
2024-06-08 19:08:08.646 10434-10434 AActivity               com.example.helloworld               D  taskid:225 ,hash:205697094
2024-06-08 19:08:08.648 10434-10434 AActivity               com.example.helloworld               D  com.example.helloworld
//跳转到A
2024-06-08 19:10:43.285 10434-10434 AActivity               com.example.helloworld               D  ----onCreate----
2024-06-08 19:10:43.293 10434-10434 AActivity               com.example.helloworld               D  taskid:225 ,hash:265426351
2024-06-08 19:10:43.296 10434-10434 AActivity               com.example.helloworld               D  com.example.helloworld
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

测试:在A中点击jump跳转到B
现象:创建了不同的实例
(视频中B是onNewIntent,是因为他的BActivity.onCreate()信息写错了,应该是onCreate)

//进入A
2024-06-08 19:18:16.649  2148-2148  AActivity               com.example.helloworld               D  ----onCreate----
2024-06-08 19:18:16.649  2148-2148  AActivity               com.example.helloworld               D  taskid:228 ,hash:165672095
2024-06-08 19:18:16.651  2148-2148  AActivity               com.example.helloworld               D  com.example.helloworld
//跳转到B
2024-06-08 19:18:35.546  2148-2148  BActivity               com.example.helloworld               D  ----onCreate----
2024-06-08 19:18:35.554  2148-2148  BActivity               com.example.helloworld               D  taskid:228 ,hash:125393259
2024-06-08 19:18:35.586  2148-2148  BActivity               com.example.helloworld               D  com.example.helloworld
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

singleTop

当要启动的目标Activity已经位于栈顶时,不会创建新的实例,会复栈用顶的Activity,并且其onNewntent()方法会被调用;
如果目标Activity不在栈顶,则跟standard一样创建新的实例。

设置android:launchMode为singleTop

<activity
            android:name=".jump.AActivity"
            android:label="A"
            android:launchMode="singleTop"
            android:exported="false" />
        <activity
            android:name=".jump.BActivity"
            android:label="B"
            android:launchMode="singleTop"
            android:exported="true">
            <intent-filter>
                <action android:name="com.example.test.BActivity" />

                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

测试:在A中点击跳转到A,再跳转到B
现象:跳转到A,hash码一致,在栈顶,所以复用实例

//进入A
2024-06-08 19:30:57.559  5429-5429  AActivity               com.example.helloworld               D  ----onCreate----
2024-06-08 19:30:57.560  5429-5429  AActivity               com.example.helloworld               D  taskid:230 ,hash:106511291
2024-06-08 19:30:57.562  5429-5429  AActivity               com.example.helloworld               D  com.example.helloworld
//跳转到A
2024-06-08 19:31:18.483  5429-5429  AActivity               com.example.helloworld               D  ----onNewIntent----
2024-06-08 19:31:18.488  5429-5429  AActivity               com.example.helloworld               D  taskid:230 ,hash:106511291
2024-06-08 19:31:18.490  5429-5429  AActivity               com.example.helloworld               D  com.example.helloworld
//跳转到B
2024-06-08 19:33:15.637  5429-5429  BActivity               com.example.helloworld               D  ----onCreate----
2024-06-08 19:33:15.638  5429-5429  BActivity               com.example.helloworld               D  taskid:230 ,hash:147131998
2024-06-08 19:33:15.641  5429-5429  BActivity               com.example.helloworld               D  com.example.helloworld
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.

singleTask

同一个任务栈中,如果要启动的目标Activity已经在栈中,则会复用该Activity,并调用其onNewIntent()方法,并且该Activity上面的Activity会被清除;如果栈中没有,则创建新的实例

没有演示

singleInstance

全局复用,不管哪个Task栈,只要存在目标Activity,就复用。每个Activity占有一个新的Task栈。

不经常使用

2024-6-8 19:55:05

4-2-1 Fragment详解(一)

2024-6-9 22:18:01

  • Fragment有自己的生命周期
  • Fragment依赖于Activity
  • Fragment通过getActivity()可以获取所在的Activity;Activity通过FragmentManager的findFragmentById()或findFragmentByTag()获取Fragment
  • Fragment和Activity是多对多的关系

AFragment
BFragment
ContainerActivity
activity_container.xml
fragment_a.xml
fragment_b.xml

4-2-2 Fragment详解(二)

  • Fragment中getActivity()为null的问题
  • 向Fragment传递参数
public static AFragment newInstance(String title) {
        AFragment fragment = new AFragment();
        Bundle bundle = new Bundle();
        bundle.putString("title", title);
        fragment.setArguments(bundle);
        return fragment;
    }


		aFragment = AFragment.newInstance("我是参数");
		getArguments().getString("title")
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.

4-2-3 Fragment详解(三)

  • Fragment回退栈
getParentFragmentManager().beginTransaction().replace(R.id.fl_container, bFragment).commitAllowingStateLoss();
  • 1.

开始测试
进入AFragment中
点击跳转BFragment
点击返回
直接到了UI界面了

addToBackStack放到回退栈中

getParentFragmentManager().beginTransaction().replace(R.id.fl_container, bFragment).addToBackStack(null).commitAllowingStateLoss();
  • 1.

测试一
进入AFragment中,打印---onCreateView---- 点击跳转BFragment
点击返回
返回到AFragment,打印---onCreateView---- 再点击返回
直接到了UI界面了

打印---onCreateView----说明:实例是同一个实例,但是视图会重新创建

测试二
进入AFragment中
点击替换文字,A变为新文字
点击跳转BFragment
点击返回
返回到AFragment,但是文字还原了

但是我们希望是改变之后的状态

replace是remove和add的组合操作

// ContainerActivity:添加tag标签a
//        getSupportFragmentManager().beginTransaction().add(R.id.fl_container, aFragment).commitAllowingStateLoss();
        getSupportFragmentManager().beginTransaction().add(R.id.fl_container, aFragment,"a").commitAllowingStateLoss();
  • 1.
  • 2.
  • 3.

先隐藏A再把B添加,放到回退栈中

Fragment fragment = getParentFragmentManager().findFragmentByTag("a");
if (fragment != null) {
	getParentFragmentManager().beginTransaction().hide(fragment).add(R.id.fl_container, bFragment).addToBackStack(null).commitAllowingStateLoss();
}else {
	getParentFragmentManager().beginTransaction().replace(R.id.fl_container, bFragment).addToBackStack(null).commitAllowingStateLoss();
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

进入AFragment中,打印---onCreateView---- 点击替换文字,A变为新文字
点击跳转BFragment
点击返回,没有打印---onCreateView---- 返回到AFragment,是替换后的状态

就是hide替代replace,因为hide不是清空只是隐藏,从而实现了堆叠效果,所以返回时能回退到非重置状态

4-2-4 Fragment详解(四)

  • Fragment和Activity的通信

公共方法
回调接口

公共方法编写步骤
1在ContainerActivity中写一个公共方法setData 2在AFragment中直接调用((ContainerActivity) getActivity()).setData("你好");

回调接口编写步骤
1在AFragment中编写接口IOnMessageClick,声明方法onClick 2ContainerActivity实现AFragment.IOnMessageClick,变重写onClick 3在AFragmentonAttach中关联Activity listener = (IOnMessageClick) context; 4AFragment中调用listener.onClick(“你好”);

2024-6-10 00:05:48

最后

2024-6-10 00:05:48

迎着日光月光星光,直面风霜雨霜雪霜。