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

版权:本作品采用「本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。」许可协议进行许可。

posted @   SpringCore  阅读(348)  评论(0编辑  收藏  举报
编辑推荐:
· 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框架的用法!
more_horiz
keyboard_arrow_up light_mode palette
选择主题
点击右上角即可分享
微信分享提示