Fragment

Fragment翻译即碎片,它被称为Android的第五大组件,主要用来附在activity上给UI进行灵活设置,模块化重复利用,支持回退栈。
与其他组件一样拥有着自己的生命周期,并且可以灵活的加载到Activity中,在开发中有很多用途。

其生命周期:
在这里插入图片描述

  • onAttach(activity: Activity)将fragment与activity绑定时调用

  • onCreateView(nflater: LayoutInflater, container:ViewGroup?, savedInstanceState: Bundle?): View?创建视图时调用

  • onActivityCreated(savedInstanceState: Bundle?)与其绑定的Activity创建完成后调用

  • onDestroyView()销毁时视图调用

  • onDetach()与Activity解绑时调用

加载:

  1. 静态加载:
    首先创建一个fragment布局文件:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#00ff00" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is fragment 1"
        android:textColor="#000000"
        android:textSize="25sp" />

</LinearLayout>

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/ll"
    android:orientation="vertical"
    >
    <fragment
        android:id="@+id/fragment"
        android:name="com.example.fragmentrecycle.MyFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </fragment>
</LinearLayout>

在这里插入图片描述
2. 动态加载:
activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/ll"
    android:orientation="vertical"
    >
    <Button
        android:onClick="click"
        android:text="添加"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </Button>
</LinearLayout>

Mactivity.kt

fun click(view: View) {
		//通过tag查找fragment管理者里有没有对应fragment
		        val findFragmentByTag = supportFragmentManager.findFragmentByTag("ss")
		if(findFragmentByTag==null){
	       	val beginTransaction = supportFragmentManager.beginTransaction()
	       	val fragment = MyFragment()
	        beginTransaction.add(R.id.fragment, fragment, "ss")
	       	beginTransaction.commit()
		}
        
   }

生命周期实验:

package com.example.fragmenttry

import android.content.Context
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        println("Life Activity onCreate")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onStart() {
        println("Life Activity onStart")
        super.onStart()
    }

    override fun onResume() {
        println("Life Activity onResume")
        super.onResume()
    }

    override fun onPause() {
        println("Life Activity onPause")
        super.onPause()
    }

    override fun onStop() {
        println("Life Activity onStop")
        super.onStop()
    }
    override fun onDestroy() {
        println("Life Activity onDestroy")
        super.onDestroy()
    }
    fun click(view: View) {
        //通过tag查找fragment管理者里有没有对应fragment
        val findFragmentByTag = supportFragmentManager.findFragmentByTag("ss")
        if(findFragmentByTag==null){
            val beginTransaction = supportFragmentManager.beginTransaction()
            val fragment = MyFragment()
            beginTransaction.add(R.id.ll, fragment, "ss")
            beginTransaction.commit()
        }

    }

}
class MyFragment: Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        println("Life MyFragment onCreateView")
        return inflater.inflate(R.layout.fragment1, container, false)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        println("Life MyFragment onCreate")
        super.onCreate(savedInstanceState)
    }

    override fun onAttach(context: Context) {
        println("Life MyFragment onAttach")
        super.onAttach(context)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        println("Life MyFragment onActivityCreated")
        super.onActivityCreated(savedInstanceState)
    }

    override fun onStart() {
        println("Life MyFragment onStart")
        super.onStart()
    }

    override fun onResume() {
        println("Life MyFragment onResume")
        super.onResume()
    }
    override fun onPause() {
        println("Life MyFragment onPause")
        super.onPause()
    }

    override fun onStop() {
        println("Life MyFragment onStop")
        super.onStop()
    }

    override fun onDestroyView() {
        println("Life MyFragment onDestroyView")

        super.onDestroyView()
    }

    override fun onDetach() {
        println("Life MyFragment onDetach")
        super.onDetach()
    }

    override fun onDestroy() {
        println("Life MyFragment onDestroy")
        super.onDestroy()
    }
}

第一次打开应用:

2020-11-29 14:44:14.949 17693-17693/com.example.fragmenttry I/System.out: Life Activity onCreate
2020-11-29 14:44:15.168 17693-17693/com.example.fragmenttry I/System.out: Life Activity onStart
2020-11-29 14:44:15.173 17693-17693/com.example.fragmenttry I/System.out: Life Activity onResume

点击按钮动态加载fragment

2020-11-29 14:46:06.875 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onAttach
2020-11-29 14:46:06.875 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onCreate
2020-11-29 14:46:06.876 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onCreateView
2020-11-29 14:46:06.883 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onActivityCreated
2020-11-29 14:46:06.883 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onStart
2020-11-29 14:46:06.883 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onResume

点击home键

2020-11-29 14:47:02.460 18116-18116/com.example.fragmenttry I/System.out: Life Activity onPause
2020-11-29 14:47:02.462 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onPause
2020-11-29 14:47:03.052 18116-18116/com.example.fragmenttry I/System.out: Life Activity onStop
2020-11-29 14:47:03.053 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onStop

回到应用:

2020-11-29 14:47:53.458 18116-18116/com.example.fragmenttry I/System.out: Life Activity onStart
2020-11-29 14:47:53.458 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onStart
2020-11-29 14:47:53.459 18116-18116/com.example.fragmenttry I/System.out: Life Activity onResume
2020-11-29 14:47:53.460 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onResume

退出应用

2020-11-29 14:48:35.523 18116-18116/com.example.fragmenttry I/System.out: Life Activity onPause
2020-11-29 14:48:35.523 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onPause
2020-11-29 14:48:36.111 18116-18116/com.example.fragmenttry I/System.out: Life Activity onStop
2020-11-29 14:48:36.112 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onStop
2020-11-29 14:48:36.114 18116-18116/com.example.fragmenttry I/System.out: Life Activity onDestroy
2020-11-29 14:48:36.114 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onDestroyView
2020-11-29 14:48:36.118 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onDestroy
2020-11-29 14:48:36.119 18116-18116/com.example.fragmenttry I/System.out: Life MyFragment onDetach

Fragment的显示和隐藏:

class MainActivity : AppCompatActivity() {
    var fragment:Fragment? = null
    var beginTransaction:FragmentTransaction? = null
    override fun onCreate(savedInstanceState: Bundle?) {
        println("Life Activity onCreate")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onStart() {
        println("Life Activity onStart")
        super.onStart()
    }

    override fun onResume() {
        println("Life Activity onResume")
        super.onResume()
    }

    override fun onPause() {
        println("Life Activity onPause")
        super.onPause()
    }

    override fun onStop() {
        println("Life Activity onStop")
        super.onStop()
    }
    override fun onDestroy() {
        println("Life Activity onDestroy")
        super.onDestroy()
    }
    fun click(view: View) {
        beginTransaction = supportFragmentManager.beginTransaction()
        when(view.id){
            R.id.add -> add()
            R.id.hide -> hide()
            R.id.show -> show()
        }
        beginTransaction?.commit()
    }
    private fun add() {
        fragment = supportFragmentManager.findFragmentByTag("fragment")
        if (fragment==null){
            fragment = MyFragment()
            beginTransaction?.add(R.id.ll, fragment!!, "fragment")
        }
    }

    private fun hide() {
        val fragment = supportFragmentManager.findFragmentByTag("fragment")
        if (fragment!=null){
            beginTransaction?.hide(fragment)
        }
    }

    private fun show() {
        val fragment = supportFragmentManager.findFragmentByTag("fragment")
        if (fragment!=null){
            beginTransaction?.show(fragment)
        }
    }

}
class MyFragment: Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        println("Life MyFragment onCreateView")
        return inflater.inflate(R.layout.fragment1, container, false)
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        println("Life MyFragment onCreate")
        super.onCreate(savedInstanceState)
    }

    override fun onAttach(context: Context) {
        println("Life MyFragment onAttach")
        super.onAttach(context)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        println("Life MyFragment onActivityCreated")
        super.onActivityCreated(savedInstanceState)
    }

    override fun onStart() {
        println("Life MyFragment onStart")
        super.onStart()
    }

    override fun onResume() {
        println("Life MyFragment onResume")
        super.onResume()
    }
    override fun onPause() {
        println("Life MyFragment onPause")
        super.onPause()
    }

    override fun onStop() {
        println("Life MyFragment onStop")
        super.onStop()
    }

    override fun onDestroyView() {
        println("Life MyFragment onDestroyView")

        super.onDestroyView()
    }

    override fun onDetach() {
        println("Life MyFragment onDetach")
        super.onDetach()
    }

    override fun onDestroy() {
        println("Life MyFragment onDestroy")
        super.onDestroy()
    }
}

从打印信息可以

  1. List item

看出它两并不会执行任何生命周期方法,就是凭空消失,如果上面有个按钮,隐藏后也点击不到!

remove(): 与add操作相反,将会销毁实例,但可以通过beginTransaction?.addToBackStack(null)把该事务放入回退栈防止实例销毁

private fun remove() {
        val fragment = supportFragmentManager.findFragmentByTag("fragment")
        if (fragment!=null){
            beginTransaction?.remove(fragment)
        }
    }
2020-11-29 15:25:59.939 25711-25711/com.example.fragmenttry I/System.out: Life MyFragment onPause
2020-11-29 15:25:59.940 25711-25711/com.example.fragmenttry I/System.out: Life MyFragment onStop
2020-11-29 15:25:59.941 25711-25711/com.example.fragmenttry I/System.out: Life MyFragment onDestroyView
2020-11-29 15:25:59.948 25711-25711/com.example.fragmenttry I/System.out: Life MyFragment onDestroy

replace(): 销毁原有,创建新的

private fun replace() {
        fragment = supportFragmentManager.findFragmentByTag("fragment")
        if (fragment!=null){
            val fragment2 = MyFragment()
            beginTransaction?.replace(R.id.ll, fragment2)
        }
    }
2020-11-29 15:29:46.353 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onAttach
2020-11-29 15:29:46.354 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onCreate
2020-11-29 15:29:46.355 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onPause
2020-11-29 15:29:46.356 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onStop
2020-11-29 15:29:46.356 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onDestroyView
2020-11-29 15:29:46.361 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onDestroy
2020-11-29 15:29:46.361 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onDetach
2020-11-29 15:29:46.362 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onCreateView
2020-11-29 15:29:46.374 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onActivityCreated
2020-11-29 15:29:46.374 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onStart
2020-11-29 15:29:46.375 27147-27147/com.example.fragmenttry I/System.out: Life MyFragment onResume

detach():销毁视图

2020-11-29 15:37:29.948 27626-27626/com.example.fragmenttry I/System.out: Life MyFragment onPause
2020-11-29 15:37:29.949 27626-27626/com.example.fragmenttry I/System.out: Life MyFragment onStop
2020-11-29 15:37:29.949 27626-27626/com.example.fragmenttry I/System.out: Life MyFragment onDestroyView

attach():重建视图

2020-11-29 15:39:49.454 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onCreateView
2020-11-29 15:39:49.466 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onActivityCreated
2020-11-29 15:39:49.466 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onStart
2020-11-29 15:39:49.467 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onResume

旋转屏幕:

2020-11-29 15:45:45.523 28424-28424/com.example.fragmenttry I/System.out: Life Activity onPause
2020-11-29 15:45:45.523 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onPause
2020-11-29 15:45:45.525 28424-28424/com.example.fragmenttry I/System.out: Life Activity onStop
2020-11-29 15:45:45.526 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onStop
2020-11-29 15:45:45.528 28424-28424/com.example.fragmenttry I/System.out: Life Activity onDestroy
2020-11-29 15:45:45.528 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onDestroyView
2020-11-29 15:45:45.530 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onDestroy
2020-11-29 15:45:45.530 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onDetach
2020-11-29 15:45:45.556 28424-28424/com.example.fragmenttry I/System.out: Life Activity onCreate
2020-11-29 15:45:45.558 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onAttach
2020-11-29 15:45:45.558 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onCreate
2020-11-29 15:45:45.600 28424-28424/com.example.fragmenttry I/System.out: Life Activity onStart
2020-11-29 15:45:45.600 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onCreateView
2020-11-29 15:45:45.603 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onActivityCreated
2020-11-29 15:45:45.604 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onStart
2020-11-29 15:45:45.605 28424-28424/com.example.fragmenttry I/System.out: Life Activity onResume
2020-11-29 15:45:45.606 28424-28424/com.example.fragmenttry I/System.out: Life MyFragment onResume

发现Activity和fragment同时销毁重建,但是fragment提供了一个retainInstance,当它等于true时j

两个fragment传递数据方式

  1. 方式一:在activity中操作,

    val arrayAdapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mString);
        val listView = findViewById<ListView>(R.id.list)
        listView?.adapter = arrayAdapter
        val mFragment2_tv = findViewById<TextView>(R.id.fragment2_tv)
        listView.setOnItemClickListener { parent, view, position, id ->
            mFragment2_tv.text = mString[position]
        }
    
  2. 方式二:在各自fragment中操作

    //从父布局找到另一个fragment的控件
    val textView = activity?.findViewById<TextView>(R.id.fragment2_tv)
    val listView = view?.findViewById<ListView>(R.id.list)
    
    val arrayAdapter =
        activity?.let { ArrayAdapter<String>(it, android.R.layout.simple_list_item_1, mString) };
    listView?.adapter = arrayAdapter
    listView?.setOnItemClickListener { parent, view, position, id ->
        textView?.text = mString[position]
    
    
  3. 方式三:通过接口

    interface titleSelectInterface {
    fun onTitleSelect(title: String?)
    }
    
    
Activity实现接口方法,在方法里调用fragment2内方法,fragment1调用activity里实现的接口方法

Fragment1:

override fun onAttach(activity: Activity) {
    super.onAttach(activity)
     try {
         mSelectInterface = activity as titleSelectInterface
     } catch (e: Exception) {
         throw ClassCastException(activity.toString() + "must implement OnArticleSelectedListener")
     }
 }
override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        mSelectInterface?.onTitleSelect(str)
    }

与ViewPager的使用方法:
看看我写了什么:
在这里插入图片描述

class MyFragmentAdapter(fm: FragmentManager, var fragmentList: List<Fragment>) : FragmentPagerAdapter(fm) {
    override fun getItem(position: Int): Fragment {
        return fragmentList.get(position)
    }
    override fun getCount(): Int {
        return  fragmentList.size
    }

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        return super.instantiateItem(container, position)
    }
}
class MyFragment1: Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment1, container, false)
    }
}
class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initView()

    }

    private fun initView() {
        var fragmentList = ArrayList<Fragment>()
        fragmentList.add(MyFragment1())
        fragmentList.add(MyFragment2())
        fragmentList.add(MyFragment3())
        fragmentList.add(MyFragment4())
        fragmentList.add(MyFragment5())
        val viewPager = findViewById<ViewPager>(R.id.viewPager);
        viewPager.adapter = MyFragmentAdapter(supportFragmentManager, fragmentList)
    }
}

activit_main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:id="@+id/ll"
    android:orientation="vertical"
    >
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"></androidx.viewpager.widget.ViewPager>
</LinearLayout>

结果:在这里插入图片描述
处理重写这两个关键方法,我们平时还会重写其他方法,这里我们直接用了Google写好的:

public Object instantiateItem(@NonNull ViewGroup container, int position) {
        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }

        final long itemId = getItemId(position);

        // Do we already have this fragment?
        String name = makeFragmentName(container.getId(), itemId);
        Fragment fragment = mFragmentManager.findFragmentByTag(name);
        if (fragment != null) {
            if (DEBUG) Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
            mCurTransaction.attach(fragment);
        } else {
            fragment = getItem(position);
            if (DEBUG) Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
            mCurTransaction.add(container.getId(), fragment,
                    makeFragmentName(container.getId(), itemId));
        }
        if (fragment != mCurrentPrimaryItem) {
            fragment.setMenuVisibility(false);
            if (mBehavior == BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
                mCurTransaction.setMaxLifecycle(fragment, Lifecycle.State.STARTED);
            } else {
                fragment.setUserVisibleHint(false);
            }
        }

        return fragment;
    }
 public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        Fragment fragment = (Fragment) object;

        if (mCurTransaction == null) {
            mCurTransaction = mFragmentManager.beginTransaction();
        }
        if (DEBUG) Log.v(TAG, "Detaching item #" + getItemId(position) + ": f=" + object
                + " v=" + (fragment.getView()));
        mCurTransaction.detach(fragment);
        if (fragment == mCurrentPrimaryItem) {
            mCurrentPrimaryItem = null;
        }
    }
public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return ((Fragment)object).getView() == view;
    }

FragmentPagerAdapter 和FragmentStatePagerAdapter区别:
FragmentPagerAdapter一般用于少量界面的ViewPager,划过的Fragment会一直保存在内存中不会被销毁,但会销毁视图。
而FragmentStatePagerAdapter适用于界面较多的ViewPager,它会保存当前的界面以及下一个界面和上一个界面,默认最多保存三个,其他的会在destroyItem()方法中被销毁掉

如何做炫酷的滑动效果:
在这里插入图片描述
需要在viewpager添加Transformer

viewPager.setPageTransformer(true, ZoomOutPageTransformer())viewPager.setPageTransformer(true, ZoomOutPageTransformer())
public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.85f;
    private static final float MIN_ALPHA = 0.5f;

    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        int pageHeight = view.getHeight();

        if (position < -1) { // [-Infinity,-1) 不可见状态
            // This page is way off-screen to the left.
            view.setAlpha(0); //透明度设置为0

        } else if (position <= 1) { // [-1,1] 可见状态,设置动画效果
            // Modify the default slide transition to shrink the page as well
            float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
            float vertMargin = pageHeight * (1 - scaleFactor) / 2;
            float horzMargin = pageWidth * (1 - scaleFactor) / 2;
            if (position < 0) {
                view.setTranslationX(horzMargin - vertMargin / 2);
            } else {
                view.setTranslationX(-horzMargin + vertMargin / 2);
            }

            // Scale the page down (between MIN_SCALE and 1)
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);

            // Fade the page relative to its size.
            view.setAlpha(MIN_ALPHA +
                    (scaleFactor - MIN_SCALE) /
                            (1 - MIN_SCALE) * (1 - MIN_ALPHA));

        } else { // (1,+Infinity] 不可见状态
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

position即该pager左边框的位置 =0时刚好贴在屏幕边框, =-1时,该pager的右边框刚好贴在屏幕左边框

startActivityForResult在FragmentActivity和Fragment中的区别

我们编写的MainActivity就是一个FragmentActivity
首先看个程序:
在这里插入图片描述

class ActivityTwo : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_two)
        setResult(10, Intent().putExtra("msg","yes"))
        finish()
    }
}
class Fragment1 : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment1, container, false)
        val button = view.findViewById<Button>(R.id.btn)
        button.setOnClickListener{
            startActivityForResult(Intent(context, ActivityTwo::class.java), 100)
        }
        return view
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (resultCode == 10){
            val stringExtra = data?.getStringExtra("msg")
            Toast.makeText(context, "Fragment "+ stringExtra+"==requestCode:"+requestCode, Toast.LENGTH_SHORT).show()
        }
        super.onActivityResult(requestCode, resultCode, data)
    }
}
class MainActivity : AppCompatActivity(){

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main3)
        val button = findViewById<Button>(R.id.btnn)
        button.setOnClickListener{
            startActivityForResult(Intent(this, ActivityTwo::class.java), 100)
        }
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (resultCode == 10){
            val stringExtra = data?.getStringExtra("msg")
            Toast.makeText(this, "FragmentActivity "+ stringExtra+"==requestCode:"+requestCode, Toast.LENGTH_SHORT).show()
        }
        super.onActivityResult(requestCode, resultCode, data)
    }
}

运行结果:
在这里插入图片描述
我们发现再FragmentActivity中嵌套Fragment时调用Fragment的startActivityForResult时,FragmentActivity也会拿到返回信息,但是requestCode时不一样的,是个比100大很多的Int,
而再FragmentActivity调用startActivityForResult时,Fragment是拿不到返回信息的。

分析:

Fragment的startActivityForResult()

public void startActivityForResult(Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}

/**
 * Call {@link Activity#startActivityForResult(Intent, int, Bundle)} from the fragment's
 * containing Activity.
 */
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
    if (mHost == null) {
        throw new IllegalStateException("Fragment " + this + " not attached to Activity");
    }
    mHost.onStartActivityFromFragment(this /*fragment*/, intent, requestCode, options);
}

mHost是FragmentActivity的一个内部类FragmentActivity.HostCallbacks
进去看看onStartActivityFromFragment(this , intent, requestCode, options);

@Override
public void onStartActivityFromFragment(
        Fragment fragment, Intent intent, int requestCode, @Nullable Bundle options) {
    FragmentActivity.this.startActivityFromFragment(fragment, intent, requestCode, options);
}
public void startActivityFromFragment(Fragment fragment, Intent intent,
            int requestCode, @Nullable Bundle options) {
    mStartedActivityFromFragment = true;
    try {
        if (requestCode == -1) {
            ActivityCompat.startActivityForResult(this, intent, -1, options);
            return;
        }
        //判断RequestCode是否越界
        checkForValidRequestCode(requestCode);
        int requestIndex = allocateRequestIndex(fragment);
        ActivityCompat.startActivityForResult(
                this, intent, ((requestIndex + 1) << 16) + (requestCode & 0xffff), options);
    } finally {
        mStartedActivityFromFragment = false;
    }
}

最重要的一句话:

ActivityCompat.startActivityForResult(
                this, intent, ((requestIndex + 1) << 16) + (requestCode & 0xffff), options);

requestIndex 是请求序号,由0递增,
简化就是(requestIndex+1)65536+requestCode,
我们上面131172 = 2
65536+100得来的
原因:使用一个简单的映射规则,把来自Fragment的请求和来自FragmentActivity自身请求区分开来,无需用户自行判断。

参考:
https://www.jianshu.com/p/6e7f894014b8

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值