IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android技术栈(一)从Activity迁移到Fragment -> 正文阅读

[移动开发]Android技术栈(一)从Activity迁移到Fragment

compile ‘com.android.support:appcompat-v7:24.+’

(注:使用24.+则表明使用 24. 开头的版本的最新版本,若直接使用+号则表明直接使用该库的最新版本。

现在可以写成:

implementation ‘androidx.appcompat:appcompat:1.1.0-alpha02’

(注:新的依赖方式implementationcompile功能相同,但是implementation无法在该模块内引用依赖的依赖,但compile可以,这么做的好处是可以加快编译速度。新的依赖方式apicompile完全相同,只是换了名字而已)

Android Studo中的Refactor->Migrate to AndroidX的选点击之后即可将项目迁移到AndroidX,在确认的时会提示你将项目备份以免迁移失败时丢失原有项目,通常情况下不会迁移失败,只是迁移的过程会花费很多的时间,如果项目很大,迁移时间会很长,这时即使Android StudioCPU利用率为0也不要关闭, 但是如果发生迁移失败,这时候就需要手动迁移了。

一些使用gradle依赖的一些第三方库中的某些类可能继承了android.support.v4包下的Fragment,但迁移到AndroidXappcompatFragment变成了androidx.fragment.app包下,原有的代码下会画红线,Android Studio也会警告你出现错误,但是不用担心,依然可以正常编译,Android Studio在编译的时候会自动完成基类的替换,但前提是你要确保你项目里的gradle.properties进行了如下设置。

android.useAndroidX=true

android.enableJetifier=tru

为了消除这些难看的红线,你可以直接将新的Fragment使用这种方式强制转换成原有的Fragment

TextureSupportMapFragment mapFragment = TextureSupportMapFragment
.class.cast(getChildFragmentManager()
.findFragmentById(R.id.map_view));

同理,也可以将旧的Fragment强制类型转换成新的Fragment.

Fragment f = Fragment.class.cast(mapFragment);

(注:上面的TextureSupportMapFragment是一个典型案例,他是高德地图SDK中的Fragment,本身已经继承了v4包下的Fragment,可以用过上面的转换来使他兼容AndroidX

差点扯远了,搞定AndroidX后,我们就可以使用FragmentActivityaddOnBackPressedCallback方法为你的Fragment提供拦截OnBackPressed的功能了.

public void addOnBackPressedCallback(@NonNull LifecycleOwner owner,
@NonNull OnBackPressedCallback onBackPressedCallback)

OnBackPressedCallback#handleOnBackPressed需要返回一个boolean值。如果你在这个回调里拦截了onBackPressed应该返回true,说明你自己已经处理了本次返回键按下的操作,这样你的Fragment就不会被弹出返回栈了。

值得注意的是,这个函数的第一个参数,一个LifecycleOwner,ActivityFragment都是LifecycleOwner,用于提供组件的生命周期,这个参数可以帮我们自动管理OnBackPressedCallback回调,你无需手动将他从Activity中移除,在LifecycleOwnerON_DESTROY事件来到的时候,他会被自动移除列表,你无需担心内存泄漏,框架会帮你完成这些事情。

/**

  • Interface for handling {@link ComponentActivity#onBackPressed()} callbacks without
  • strongly coupling that implementation to a subclass of {@link ComponentActivity}.
  • @see ComponentActivity#addOnBackPressedCallback(LifecycleOwner, OnBackPressedCallback)
  • @see ComponentActivity#removeOnBackPressedCallback(OnBackPressedCallback)
    /
    public interface OnBackPressedCallback {
    /
    *
  • Callback for handling the {@link ComponentActivity#onBackPressed()} event.
  • @return True if you handled the {@link ComponentActivity#onBackPressed()} event. No
  • further {@link OnBackPressedCallback} instances will be called if you return true.
    */
    boolean handleOnBackPressed();
    }

我们可以看到Activity内管理的OnBackPressedCallback的执行循序与添加时间有关.最后被添加进去的能最先得到执行.

public void addOnBackPressedCallback(@NonNull LifecycleOwner owner,
@NonNull OnBackPressedCallback onBackPressedCallback) {
Lifecycle lifecycle = owner.getLifecycle();
if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
// Already destroyed, nothing to do
return;
}
// Add new callbacks to the front of the list so that
// the most recently added callbacks get priority
mOnBackPressedCallbacks.add(0, new LifecycleAwareOnBackPressedCallback(
lifecycle, onBackPressedCallback));
}

可以看到它是添加到mOnBackPressedCallbacks这个List的最前面的.

Fragment是必须要有id的,使用getId可以返回自身的id,通常用这个方法返回它所在的容器的id,供其他Fragment添加进FragmentManager时使用。(比如说你使用了一个FrameLayout作为Fragment的容器,那么它就会返回那个FrameLayoutid)

/**

  • Return the identifier this fragment is known by. This is either
  • the android:id value supplied in a layout or the container view ID
  • supplied when adding the fragment.
    */
    final public int getId() {
    return mFragmentId;
    }

startFragmentForResult方法在哪?对不起和OnBackPressed一样,Google没有直接为我们实现这个方法,但这并不代表Fragment没有这个功能,你当然可以直接用定义getter的方式来获取Fragment上内容,但这并不是最佳实践,为了规范编码我们最好还是使用公共的API

Fragment#setTargetFragment可以给当前Fragment设置一个目标Fragment和一个请求码

public void setTargetFragment(@Nullable Fragment fragment, int requestCode)

当当前Fragment完成相应的任务后,我们可以这样将返回值送回给我们的目标Fragment通过Intent

getTargetFragment().onActivityResult(getTargetRequestCode(),
Activity.RESULT_OK,new Intent());

不过要注意,目标Fragment和被请求的Fragment必须在同一个FragmentManager的管理下,否则就会报错

最后,当我们在使用Fragment#getActivity()时返回的是一个可空值,如果没有判空检查在Android Studio中将会出现一个恶心的黄色警告,你可以使用requireActivity()来代替它,同样的方法还有requireFragmentManager()等.

3.Fragment生命周期

这可能是最让人懊恼的部分之一了。下面是绝对的高能区,因为接下来的那一张图,彰显了Fragment中最让人恐惧的一部分,它的生命周期.

本来笔者想要用ProcessOn,自己画一张Fragment生命周期的流程图.怎么说我都是软件工程专业的啊,最后…真香,因为这图实在是太复杂了,真要画它时间上有点过不去,所以我只好拿来主义.

下图展示了各回调发生的时间顺序:

image.png

捋一下,常用的回调有这些,觉得上面有图有点烦的话的话那就看下面总结的文字吧:

  • onInflate(Context,AttributeSet,Bundle)只有硬编码在xml中的Fragment(即使用fragment标签)才会调用该方法,与自定义View十分类似,在实例化xml布局时该方法会被调用

  • onAttach(Context)执行该方法时,FragmentActivity已经完成绑定,该方法传入一个Context对象,实际上就是该Fragment依附的Activity,此时调用getActivity将不会返回null,但是Activity#onCreate可能还有没有执行。

  • onCreate(Bundle)用来初始化Fragment。可通过参数savedInstanceState获取之前保存的值。

  • onCreateView(LayoutInflater,ViewGroup,Bundle)需要返回一个View用来初始化Fragment的布局。默认返回null,值得注意的是,若返回null Fragment#onViewCreated将不会执行。使用ViewPager+Fragment时此方法可能会被多次调用。

  • onActivityCreated(Bundle)执行该方法时,与Fragment绑定的ActivityonCreate方法已经执行完成并返回,若在此之前与Activity交互,若引用了未初始化的资源会应发空指针异常。

  • onStart()执行该方法时,Fragment所在的Activity由不可见变为可见状态

  • onResume()执行该方法时,Fragment所在的Activity处于活动状态,用户可与之交互

  • onPause()执行该方法时,Fragment所在的Activity处于暂停状态,但依然可见,用户不能与之交互

  • onStop()执行该方法时,Fragment所在的Activity完全不可见

  • onSaveInstanceState(Bundle)保存当前Fragment的状态。该方法会自动保存Fragment的状态,比如EditText键入的文本,即使Fragment被回收又重新创建,一样能恢复EditText之前键入的文本。

  • onDestroyView()销毁与Fragment有关的视图,但未与Activity解除绑定,一般在这个回调里解除Fragment对视图的引用。通常在ViewPager+Fragment的方式下会使用并重写此方法,并且与Fragment#onCreateView一样可能是多次的。

  • onDestroy()销毁Fragment。通常按Back键退出或者Fragment被移除FragmentManager时调用此方法,此时应该清理Fragment中所管理的所有数据。

  • onDetach()解除与Activity的绑定。在onDestroy方法之后调用。若在此时getActivity(),你将会得到一个null

4.Fragment的替代方案

看了那么多有关Fragment的介绍,如果你还对Fragment嗤之以鼻,又想减小业务的逻辑的粒度,那么我只能给你Fragment的替代方案了。

一位square公司(对就是那个诞生了Retrofitokhttp的公司)的工程师开发的Fragment替代方案《View框架flow》,以及相关博文,国内有优秀的简书作者翻译了这篇文章《(译)我为什么不主张使用Fragment》,原作者在这篇文章中痛斥了Fragment的各种缺点,我想你可能会喜欢这个.

5.结语

好了关于从Activity迁移到Fragment的介绍差不多就到这了,我也是想到什么就写什么,所以文章的结构可能会有些乱,以后如果还有其他知识点我会慢慢补充上来.

【附】相关架构及资料

Android高级技术大纲

资料及源码领取

点赞+加群免费获取?Android?IOC架构设计

想到什么就写什么,所以文章的结构可能会有些乱,以后如果还有其他知识点我会慢慢补充上来.

【附】相关架构及资料

[外链图片转存中…(img-BiBU8jhx-1641135749522)]

资料及源码领取

点赞+加群免费获取?Android?IOC架构设计
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-01-04 13:32:50  更:2022-01-04 13:35:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年2日历 -2025/2/1 1:50:46-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码