Android学习笔记(六)-----Activity与Fragment

 

4-1-1 Activity的创建

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

在AndroidManifest.xml里可设置

android:theme:设置主题样式

android:screenOrientation:用于控制activity启动时方向,一般设置竖屏或横屏显示

android:launchMode:设置启动模式,具体参考https://www.jianshu.com/p/404964d344d3

<intent-filter>:用于设置默认启动的Activity

4-1-2 Activity的生命周期

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

1. 显示跳转和隐式跳转

各种跳转方式

                //显示跳转1
                Intent intent = new Intent(AActivity.this, BActivity.class);
                startActivity(intent);

                //显示跳转2
                Intent intent = new Intent();
                intent.setClass(AActivity.this, BActivity.class);
                startActivity(intent);

                //显示跳转3
                Intent intent = new Intent();
                intent.setClassName(AActivity.this, "com.example.hao.helloworld.jump.BActivity");
                startActivity(intent);

                //显示跳转4
                Intent intent = new Intent();
                intent.setComponent(new ComponentName(AActivity.this,                          "com.example.hao.helloworld.jump.BActivity"));
                startActivity(intent);

                //隐式跳转
                Intent intent = new Intent();
                intent.setAction("com.example.test.BActivity");
                startActivity(intent);

以上就是各种跳转方式,常用的也就第一种显示跳转1

其中隐式跳转中需要在AndroidManifest.xml里对要跳转的Activity设置<intent-filter>

<intent-filter>
    <action android:name="com.example.test.BActivity" />//这个就是要跳转的action名

    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

2.Activity之间的数据传递

通过intent.putExtra()来传递,但是查看源码发现,实质上是新建了一个Bundle()

    public Intent putExtra(String name, boolean value) {
        if (mExtras == null) {
            mExtras = new Bundle();
        }
        mExtras.putBoolean(name, value);
        return this;
    }

 至于Intent本身就可以传递参数(Intent.putExtra("key", value))但为什么要用Bundle,参考https://www.jianshu.com/p/e9db0797293b

扫描二维码关注公众号,回复: 8990415 查看本文章

AActivity传递数据:

                Intent intent = new Intent(AActivity.this, BActivity.class);
                Bundle bundle = new Bundle();
                bundle.putString("name","helloworld");
                bundle.putInt("number",88);
                intent.putExtras(bundle);
                startActivity(intent);

BActivity接收数据:

Bundle bundle = getIntent().getExtras();
String name = bundle.getString("name");
int number = bundle.getInt("number");

3.startActivityForResult

如果想在Activity中得到新打开的Activity 关闭后返回的数据,则需要使用startActivityForResult(Intent intent, int requestCode)方法打开新的Activity,新的Activity 关闭后会向前面的Activity传回数据,为了得到传回的数据,必须在前面的Activity中重写onActivityResult(int requestCode, int resultCode, Intent data)方法。

传回数据同传出数据一样,也是通过Bundle来实现

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        ToastUtil.showMsg(AActivity.this, data.getExtras().getString("title"));
    }

重写方法来接收传回来的数据,这里用的是自定义的封装的Toast

data.getExtras().getString()接收传回来的String

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

android:launchMode属性

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

  • standard:标准模式,默认,每次启动Activity时(startActivity),都创建Activity实例,并放入任务栈;
  • singleTop:Task栈顶复用模式,如果某个Activity自己激活自己,即任务栈栈顶就是该Activity,则不需要创建实例,其余情况都要创建Activity实例;
  • singleTask:Task栈内复用模式,如果要激活的那个Activity在任务栈中存在实例,则不需要创建实例,只需要把此Activity放入栈顶,并把该Activity以上的Activity实例都pop;
  • singleInstance:全局单例模式,相当于全局的实例,其他Activity若有该实例便可复用

 AActivity和BActivity跳转实例,会输出实例相关信息

AActivity:

        Log.d("AActivity","----onCreate----");
        Log.d("AActivity","taskid:"+getTaskId()+" ,hash:"+hashCode());
        logTaskName();



    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.d("AActivity","----onNewIntent----");
        Log.d("AActivity","taskid:"+getTaskId()+" ,hash:"+hashCode());
        logTaskName();
    }



    private void logTaskName(){
        try {
            ActivityInfo info = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
            Log.d("AActivity", info.taskAffinity);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

BActivity:

        Log.d("BActivity","----onNewIntent----");
        Log.d("BActivity","taskid:"+getTaskId()+" ,hash:"+hashCode());
        logTaskName();




    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        Log.d("BActivity","----onNewIntent----");
        Log.d("BActivity","taskid:"+getTaskId()+" ,hash:"+hashCode());
        logTaskName();
    }

    private void logTaskName(){
        try {
            ActivityInfo info = getPackageManager().getActivityInfo(getComponentName(), PackageManager.GET_META_DATA);
            Log.d("AActivity", info.taskAffinity);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
    }

1.Standard 

这是开启AActivity时输出的debug信息

点击跳转到AAcitvity(也就是跳转到本身),发现只有hashcode发生了改变,也就是重新创建了AActivty的实例

点击JUMP会跳转到BActivity,输出信息如下,发现也是只有hashcode发生变化,说明BActivity也是新建的实例

2.singleTop

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

开启AAcitvity时输出的信息:

再点击跳转到AAcitvity输出的信息:

可以看到并未调用onCreate()方法,而是调用了onNewIntent()方法,复用了AActivity

再点击JUMP(跳转到BActivity)输出的信息:

新建了一个BActivity实例,以为BActivity不在栈顶

3.singleTask

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

在AndroidManifest.xml对AActivity的taskName进行了设置:

android:launchMode="singleTask"
android:taskAffinity="com.example.hao.helloworld.singletask"

启动AActivity时输出信息为:

再点击跳转到AAcitvity输出的信息:

可以看到很明显的复用了AActivity

再点击JUMP(跳转到BActivity)输出的信息:

发现新建了一个任务栈,id为10,name为:com.example.hao.helloworld

再从BActivity跳转回AActivity时AActivity输出的信息:

发现也是复用了AActivity

4.singleInstance(较少使用)

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

4-2-1 Fragment详解(一)

创建一个主Actiity:ContainerActivity和两个Fragment:AFragmen和BFragment

然后avtivity_container.xml设置如下,一个按钮,一个Fragment

<Button
    android:id="@+id/btn_change"
    android:layout_width="match_parent"
    android:layout_height="50dp"
    android:text="更换Fragment"/>

<FrameLayout
    android:id="@+id/fl_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/btn_change">

</FrameLayout>

Fragment组件将使用AFragment或BFragment

AFragment的布局文件如下(BFragment和AFragment一样):

<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"/>

再在AFragment(BFragment也一样)绑定到layout

public class AFragment extends Fragment {

    private TextView mTvTitle;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_a, container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        mTvTitle = (TextView) view.findViewById(R.id.tv_title);
    }
}

在ContainerActivity添加Fragment


        //实例化AFragment
        aFragment = new AFragment();
        //把AFragment添加到Activity,记得调用commit
        getFragmentManager().beginTransaction().add(R.id.fl_container, aFragment).commitAllowingStateLoss();

使用Fragment时,可以通过用户交互来执行一些动作,比如增加、移除、替换等。所有这些改变构成一个集合,这个集合被叫做一个transaction。然后需要调用commit()方法,将这些变化应用。至于commit()和commitAllowingStateLoss()区别,需要自己了解

getFragmentManager().beginTransaction().replace(R.id.fl_container, bFragment).commitAllowingStateLoss();

replace是替换Fragment

4-2-2 Fragment详解(二)

 1.getActivity()为null的问题

最好采用如下方法获取Activity

if(getActivity() != null){
    //
}else {

}

2.向Fragment传递参数

在Fragment中设置如下:

    public static AFragment newInstance(String title){
        AFragment aFragment = new AFragment();
        Bundle bundle = new Bundle();
        bundle.putString("title", title);
        aFragment.setArguments(bundle);
        return aFragment;
    }

至于为什么 要通过Bundle来传递参数,因为Activity重新创建时,会重新构建它所管理的Fragment,原先的Fragment的字段值将会全部丢失,但是通过Fragment.setArguments(Bundle bundle)方法设置的bundle会保留下来。

然后在onViewCreated中设置

mTvTitle = (TextView) view.findViewById(R.id.tv_title);
if(getArguments() != null){
    mTvTitle.setText(getArguments().getString("title"));
}

最后在Activity中实例化Fragment时调用

aFragment = AFragment.newInstance("我是参数");
发布了38 篇原创文章 · 获赞 6 · 访问量 3419

猜你喜欢

转载自blog.csdn.net/qq_37704124/article/details/84862900