Android -- Activity和Fragment
⒈简介
我们在App上看到的每一个界面它就需要一个Activity,但Activity并不等同于界面,只是界面需要Activity。
Fragment是碎片化的界面,每一个Activity可以包含很多个Fragment,Fragment不可以作为独立存在的,它必须依赖于Activity,它是受Activity管理的。
⒉Activity的创建三部曲
1.新建类继承Activity或其子类
package cn.coreqi.activity; import androidx.appcompat.app.AppCompatActivity; public class TestActivity extends AppCompatActivity { }
2.在AndroidManifest中声明
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.coreqi.helloworld2"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name="cn.coreqi.activity.TestActivity"></activity> <activity android:name=".ButtonActivity"></activity> <activity android:name=".TextViewActivity" /> <!-- 注册 activity --> <activity android:name=".MainActivity"> <!-- .前面默认会加包名,上面声明了包名,此处为cn.coreqi.helloworld2.MainActivity --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <!-- 设置当前activity为应用启动的第一个activity --> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
3.创建layout文件(布局文件)并在Activity的onCreate中设置。
在res/layout下新建布局文件
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> </LinearLayout>
并且在Activity的onCreate方法中设置
package cn.coreqi.activity; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import cn.coreqi.helloworld2.R; public class TestActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); } }
一些小技巧
设置Activity标题头
<activity android:name=".MainActivity" android:label="启动页"> <!-- .前面默认会加包名,上面声明了包名,此处为cn.coreqi.helloworld2.MainActivity --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <!-- 设置当前activity为应用启动的第一个activity --> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
取消标题头(单个Activity)
<activity android:name=".MainActivity" android:theme="@style/Theme.AppCompat.Light.NoActionBar"> <!-- .前面默认会加包名,上面声明了包名,此处为cn.coreqi.helloworld2.MainActivity --> <intent-filter> <action android:name="android.intent.action.MAIN" /> <!-- 设置当前activity为应用启动的第一个activity --> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
取消标题头(全局Activity)
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.AppCompat.Light.NoActionBar">
设置Activity的屏幕方向
<activity android:name="cn.coreqi.activity.TestActivity" android:screenOrientation="portrait"></activity><!--竖屏显示-->
设置Activity的启动模式
<activity android:name="cn.coreqi.activity.TestActivity" android:launchMode="singleInstance"></activity>
⒊Activity的生命周期
一个Activity被部署到安卓应用之后跟随应用进程运行,它会在不同的状态之间进行切换,并且在切换状态的同时也会回调相应的方法,我们把Activity不同的状态称之为Activity的生命周期。
当点击进入Activity时,执行三个Activity生命周期方法,分别是onCreate、onStart、onResume,点击返回按钮时,执行三个生命周期方法,分别是onPause(暂停)、onStop(停止)、onDestroy(摧毁)。
停留界面切换到后台,这时候Activity将会运行到onPaue(暂停)及onStop(停止)方法中去,切换回来后,Activity将会运行onResume方法
常用的生命周期方法,onCreate,onResume(数据刷新等),onPause(当前数据暂停)、onDestroy(当前页面摧毁需要做的事情)。
⒋Active的跳转和数据传递
跳转
-
- 显式跳转
//显示跳转1 Intent intent1 = new Intent(AActivity.this,BActivity.class); //Intent 意图 startActivity(intent1); //显示跳转2 Intent intent2 = new Intent(); intent2.setClass(AActivity.this,BActivity.class); startActivity(intent2); //显示跳转3 Intent intent3 = new Intent(); intent3.setClassName(AActivity.this,"cn.coreqi.activity.BActivity"); startActivity(intent3); //显示跳转4 Intent intent4 = new Intent(); intent4.setComponent(new ComponentName(AActivity.this,"cn.coreqi.activity.BActivity")); startActivity(intent4);
-
- 隐式跳转
<activity android:name="cn.coreqi.activity.BActivity"> <intent-filter> <action android:name="fanqi.BActivity"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
//隐式调用 Intent intent1 = new Intent(); intent1.setAction("fanqi.BActivity"); startActivity(intent1);
Activity之间的数据传递
//传递 Intent intent = new Intent(AActivity.this,BActivity.class); //intent.putExtra("name","fanqi"); Bundle bundle = new Bundle(); //数据的传递通过Bundle bundle.putString("name","fanqi"); intent.putExtras(bundle); startActivity(intent);
//接收 Bundle bundle = getIntent().getExtras(); String name = bundle.getString("name"); Log.d("t",name);
startActivityForResult:启动Activity,结束后返回结果。
Intent intent = new Intent(AActivity.this,BActivity.class); //将请求码为0的数据携回 startActivityForResult(intent,0);
//返回数据 Bundle bundle = new Bundle(); bundle.putString("name","fanqi"); Intent intent = new Intent(); intent.putExtras(bundle); setResult(Activity.RESULT_OK,intent); finish();
@Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); Log.d("requestCode",String.valueOf(requestCode)); Log.d("resultCode",String.valueOf(resultCode)); Log.d("data",data.getExtras().getString("name")); }
⒌Activity的4种启动模式
Activity的android:launchMode属性
-
- standard:标准模式,默认【每启动一个Activity就会去创建这个Activity新的实例,不管这个Activity之前有没有启动过,是否存在,只要启动,就会创建新的实例】
- singleTop:Task栈顶复用模式【当我们启动一个Activity,如果我们要启动的Activity位于栈的栈顶,那么就不会去创建新的实例,而是会直接复用这个栈顶的Activity,如果Activity实例不在栈顶或者实例根本不存在,那么还是会去创建一个新的实例】
- singleTask:Task栈内复用模式【只要栈里面存在我们需要的Activity实例,就可以复用】
- singleInstance:全局单例模式【全局复用模式,会在当前应用所有的栈里面复用。】
Activity是由任务栈管理的,每启动一个Activity,就会被放入栈中,按返回键,就会从栈顶移除一个Activity。
standard是默认的启动模式,即标准模式,每启动一个Activity,都会创建一个新的实例。
<activity android:name="cn.coreqi.activity.BActivity" android:launchMode="standard"> <intent-filter> <action android:name="fanqi.BActivity"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
singleTop:当要启动的目标Activity已经位于栈顶时,不会创建新的实例,会复用栈顶的Activity,并且其onNewIntent()方法会被调用;如果目标Activity不在栈顶,则跟standard一样创建新的实例。
singleTask:在同一个任务栈中,如果要启动的目标Activity已经在栈中,则会复用该Activity,并调用其onNewIntent()方法,并且该Activity上面的Activity会被清除;如果栈中没有,则创建新的实例。
**设置Activity任务栈名称
<activity android:name="cn.coreqi.activity.BActivity" android:launchMode="standard" android:taskAffinity="fanqi.task"> </activity>
singleInstance:全局复用,不管哪个Task栈,只要存在目标Activity,就复用。每个Activity占有一个新的Task栈。【应用的相当少,如果我们的Activity需要频繁的被其他应用所调用】
⒍Fragment
Fragment有自己的生命周期
Fragment依赖于Activity【当Activity销毁的时候Fragment会同步被销毁】
Fragment通过getActivity()可以获取所在的Activity;Activity通过FragmentManager的findFragmentById()或findFragmentByTag()获取Fragment
Fragment和Activity是多对多的关系【一个Fragment可以存在于多个Activity当中,可以被多个Activity所包含,多个Fragment也可以在一个Activity当中】
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textColor="#000000" android:textSize="20sp" android:text="我是AFragment" android:gravity="center"/> </LinearLayout>
package cn.coreqi.fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import cn.coreqi.helloworld2.R; public class AFragment extends Fragment { private TextView mTvTitle; @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_a,container,false); return view; } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); mTvTitle = view.findViewById(R.id.tv_title); } }
package cn.coreqi.fragment; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import cn.coreqi.helloworld2.R; public class ContainerActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_container); AFragment aFragment = new AFragment(); //把AFragment添加到Activity指定的位置中,记得调用commit getSupportFragmentManager().beginTransaction().add(R.id.fl_container,aFragment).commitAllowingStateLoss(); } }
⒎一些Fragment常见问题
Fragment中getActivity()为null的问题
1.使用if进行判断
2.在Fragment子类中声明Activity变量并在Fragment的声明周期中赋值(可能内存泄漏,最好不要用)。
如何向Fragment传递参数
Fragment.setArguments()
Fragment.getArguments()
⒏Fragment回退栈
一个Activity它是由任务栈管理的,每启动一个Activity都会把它放到任务栈中,这时候每按下返回键,就会依次从栈顶弹出一个Activity,这是一个回退的过程。
Fragment同样可以达到这样的一个过程,往一个Activity中and了多个Fragment,按下返回键时,把这些Fragment依次回退。
AFragment aFragment = new AFragment(); //把AFragment添加到Activity指定的位置中,记得调用commit getSupportFragmentManager().beginTransaction().add(R.id.fl_container,aFragment).commitAllowingStateLoss(); //用BFragment替换AFragment,并添加到回退栈中去。这样按下返回键就不会回退到上一个Activity。 //**虽然返回到AFragment还是以前的实例,但是AFragment的视图会被重新渲染,即会调用AFragment的onCreateView方法 BFragment bFragment = new BFragment(); getSupportFragmentManager().beginTransaction().replace(R.id.fl_container,bFragment).addToBackStack(null).commitAllowingStateLoss(); //如果不要AFragment的视图被重新渲染,即不要调用replace方法,因为replace方法本质上是先remove然后再add AFragment aFragment = new AFragment(); //把AFragment添加到Activity指定的位置中,记得调用commit getSupportFragmentManager().beginTransaction().add(R.id.fl_container,aFragment,"a").commitAllowingStateLoss(); Fragment fragment = getSupportFragmentManager().findFragmentByTag("a"); if(fragment != null){ getSupportFragmentManager().beginTransaction().hide(fragment).add(R.id.fl_container,bFragment).addToBackStack(null).commitAllowingStateLoss(); }else{ getSupportFragmentManager().beginTransaction().replace(R.id.fl_container,bFragment).addToBackStack(null).commitAllowingStateLoss(); }
⒐Fragment和Activity的通信
在Activity中提供一个方法完成对私有字段(数据)的修改
public void setData(String text){ mTvTitle.setText(text); }
在Fragment中使用getActivity
((ContainerActivity)getActivity()).setData("fanqi");
还有一种更加推荐的方式
在Acticity中去实现一个在Fragment中声明的接口,通过回调接口去实现数据的传递
首先,在Fragment的实现类中去声明一个接口
public interface IOnMessageClick{ void onClick(String text); }
然后,在Activity的子类中去实现它
public void setData(String text){ mTvTitle.setText(text); }
其次,在Fragment的实现类中声明接口的私有变量,并重写onAttach(Context context)方法
private IOnMessageClick listener; /** * 当Fragment被应用到Activity的时候,Fragment的onAttach方法会被调用 * @param context 即应用的Activity */ @Override public void onAttach(Context context) { super.onAttach(context); try { listener = (IOnMessageClick) context; }catch (ClassCastException e){ throw new ClassCastException("Activity 必须实现 IOnMessageClick接口"); } } public void test(){ //使用 listener.onClick("fanqi"); }
作者:奇
出处:https://www.cnblogs.com/fanqisoft/p/12165145.html
版权:本作品采用「本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。」许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!