《一个Android工程的从零开始》-6、base(五) BaseFragment封装

2024-05-16 14:08

本文主要是介绍《一个Android工程的从零开始》-6、base(五) BaseFragment封装,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

先扯两句

首先呢,要先跟大家道个歉,之前结束BaseActivity部分和写ButterK的部分都有些兴奋,博客发出去以后,竟然忘了将代码提交git了,一打开项目,看都是绿色、蓝色的文件,实在是不好意思,已经提交了,有需要的可以去查看了。 我的代码都是随着写博客随着完善的,所以希望今天的最后能够想起来提交,不然。。。大家不要打我,我怕疼。。。
MyBaseApplication (https://github.com/BanShouWeng/MyBaseApplication)

正文

Fragment基本方法

前面也提到了,上一篇已经将BaseActivity封装结束了,当然只是一些基本的操作,在后续的过程中,肯定会随着新功能的运用逐步去完善。 而今天我们所研究的内容呢,看到标题大家自然也就明白了,就是BaseFragment的封装,当然,与前一段所说一样,这个部分的内容也是暂时性的一些基础内容,并不是说今天的内容搞定了,以后都不需要进到BaseFragment中做任何修改了的,所以因人而异,因项目而异。 之前都是先分析,再贴代码,今天改改套路,先开个大:

package com.banshouweng.mybaseapplication.base;import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;import com.banshouweng.mybaseapplication.R;/*** 《一个Android工程的从零开始》*@author 半寿翁*@博客:*@ CSDN http://blog.csdn.net/u010513377/article/details/74455960*@ 简书  http://www.jianshu.com/p/1410051701fe*/
public class BaseFragment extends Fragment {private OnFragmentInteractionListener mListener;private Unbinder unbinder;public BaseFragment() {// Required empty public constructor}/*** Use this factory method to create a new instance of* this fragment using the provided parameters.** @return A new instance of fragment BaseFragment.*/// TODO: Rename and change types and number of parameterspublic static BaseFragment newInstance() {BaseFragment fragment = new BaseFragment();return fragment;}@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (getArguments() != null) {}}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,unbinder = ButterKnife.bind(this, view);// Inflate the layout for this fragmentreturn inflater.inflate(R.layout.fragment_base, container, false);}// TODO: Rename method, update argument and hook method into UI eventpublic void onButtonPressed(Uri uri) {if (mListener != null) {mListener.onFragmentInteraction(uri);}}@Overridepublic void onAttach(Context context) {super.onAttach(context);if (context instanceof OnFragmentInteractionListener) {mListener = (OnFragmentInteractionListener) context;} else {throw new RuntimeException(context.toString()+ " must implement OnFragmentInteractionListener");}}@Overridepublic void onDetach() {super.onDetach();mListener = null;}@Overridepublic void onDestroyView() {super.onDestroyView();unbinder.unbind();}/*** This interface must be implemented by activities that contain this* fragment to allow an interaction in this fragment to be communicated* to the activity and potentially other fragments contained in that* activity.* <p>* See the Android Training lesson <a href=* "http://developer.android.com/training/basics/fragments/communicating.html"* >Communicating with Other Fragments</a> for more information.*/public interface OnFragmentInteractionListener {// TODO: Update argument type and namevoid onFragmentInteraction(Uri uri);}
}

细心的或许会发现,我把包名给改了,填上banshouweng,实在是所以找的demo之类的都有这类的,没办法,网上找的demo都有类似的个人推广,我怎么忍心不给自己也添加一个呢,嘿嘿。
好了,进入正题。
上面呢,是创建一个block fragment后,AS自动给生成的一系列方法,当然,如果你也创建一个,应该会比我这个内容更多,因为上面贴出来的已经是经过我筛选过的了,毕竟你让一个喜欢偷懒的人,上来就看那么多的代码,反正我个人是忍不了。
下面就说一下我留下的这些代码都有上面用:

  1. BaseFragment
    构造方法,这里面暂时唯一一个没有用到的方法,留下它的目的只是单纯的为了与下面的newInstance做对比,当然,如果不适用onCreate中的getArgument传递参数的时候,可以用构造方法传参,只不过现在都很少使用了罢了。
  2. newInstance
    这里的作用与上面的构造方法相同,毕竟可以看到,其中就只有一个构造方法罢了,至于为什么当下很流行使用newInstance而不使用构造方法,主要还是为了去耦合。好吧,我也比较讨厌这些看起来特别高大上的专业词汇。就我个人理解,使用它最好的一种玩法就是复用,如果使用构造方法的时候,就只能创建一个对象,而如果将newInstance中创建的对象放在变成全局变量,再做个判空处理,你就会发现,这里我们可以在多场合使用同一个对象,都不用传参数了,甚至连状态都保留了。(以上说明的是对newInstance与构造方法的区别,并不仅限于Fragment)
  3. onCreate
    用于获取argument,也就是从Activity中传递来的参数获取,暂时没有发现其他用处。
  4. onCreateView与onViewCreated(上面代码中没有)以及onDestroyView
    onCreateView是当视图创建前执行,onViewCreated是在视图创建完毕后执行,是一对,一般是用来解析布局的,当然如果看了我上一篇博客,应该会看到其中写的一段,关于ButterKnife.findById在Fragment中运用的,其中的view参数就可以使用这里解析的布局代替,而这个方法的使用就是在onViewCreated中,同时在onViewCreated方法运行之后,才可以对我们的控件做操作,不然很容易出现空指针异常。而onCreateView与onDestroyView这一对的使用则是ButterKnife的绑定与解绑,方法参见前面的代码就可以。
  5. onAttach
    Fragment与Activity绑定时执行的方法,有的时候在Fragment中使用getActivity会报空指针异常,所以这个时候我们就需要onAttach来帮忙了,因为你会看到,它的参数正是Context,只要将它保存起来,在使用的时候直接调用就可以解决这个问题了。不过也正因为这个操作我们在BaseFragment封装时做了操作,所以一般直接使用Context,也就不需要再去调用它了。
  6. onDetach
    与上面的onAttach方法可以算做一对,上面是绑定Activity的方法,onDetach则是解绑时执行的方法,而这个方法中做的操作,就是将我们整个Fragment中使用到的与Activity相关联的参数置空,防止发生OOM。
  7. OnFragmentInteractionListener与onButtonPressed
    这个部分是之前还打算自己写的内容,没想到现在AS已经为我们提出了解决方法。作用就是将Fragment中的参数传递到Activity中,AS生成的这个传递的是Uri,我们在使用的时候,可以自行定义所要传递的内容,同样也可以在接口中写添加其他的抽象方法,而不需要的时候也可以不写。onButtonPressed的目的是告诉我们这个部分的代码应该如何使用,根据自己的需求灵活运用即可。

BaseFragment封装

其实这个部分呢,说起来复杂,可也比较简单,毕竟之前我们已经封装过了BaseActivity,很多的方法都是共通的,所以对应的部分,我们只需要粘贴过来,略作修改即可,所以这里,我就将我们一些有差异的地方写出来,其他的部分,大家看一下代码就好。

方法封装

写BaseActivity的时候,我们是先从布局开始的,为了公平起见,写BaseFragment就从方法封装开始好了。
当然,如果你真的认为我这么安排是什么所谓的公平,那就只能说明你太单纯了,作为我们这么一个懒人,哪有什么时间去考虑什么公平,有那时间睡觉多好。所以这么安排只有一个原因,那就是方法的封装更简单。
不过在方法封装之前,我们有一件事需要处理一下,也就是刚刚onAttach中所说的内容。而且对于这部分,看过我前面博客的应该会了解到,在写BaseActivity方法封装的时候,说到了为什么会专门创建两个对象,Context和Activity,就是为了与Fragment中引用的向统一,至于这两个对象是否还有其他作用就有待我们将来探索了,但是在Fragment中可以肯定是很必要的。
既然必要那就创建之,上代码:

    /*** 用于传递的上下文信息*/public Context context;public Activity activity;@Overridepublic void onAttach(Context context) {super.onAttach(context);this.context = context.getApplicationContext();activity = (Activity) context;}

以上就完成了获取Context和Activity的操作,后面Fragment的运用中很大程度上依赖这两个对象,这部分个人的建议就是,直接将BaseActivity中的方法复制过来,然后就会看到个别报错的地方,然后在调用的方法前面添加上“activity. ”,this判断是否与所绑定的Activity有关,有的替换成activity,没有的替换成context,就完成了方法的封装,例如:

    //报错部分public void startActivity(Class<?> clz) {startActivity(new Intent(this, clz));}//修改之后public void startActivity(Class<?> clz) {startActivity(new Intent(context, clz));}//修改前case R.id.base_back:if (isResetBack) {onClickBack.clickBack();} else {finish();}break;//修改后case R.id.base_back:if (isResetBack) {onClickBack.clickBack();} else {activity.finish();}break;

这么多代码直接针贴过来就可以,包括网络监听以及进度条的部分,当然,如果实在偷懒,进度条的部分可以不用复制过来,而是在需要使用的Fragment中,使用上面说到的接口OnFragmentInteractionListener直接调用BaseActivity中的进度条。
最后需要说明的一点,个人建议,将BaseActivity在onCreate中执行的方法调用都放置在onViewCreated方法中进行,放置出现没有必要的空指针。

Title

看到标题大家应该知道,前面我们已经将方法封装完成了,对于这种可以偷懒的任务我可是相当喜欢了。
可是很不幸的是,这次需要花些心思的竟然落在Title上,不过好在难度有限,让我这样的懒人很感动啊。

Title的封装

哎,看到Title,我就又想起来第一篇博客里面的那三种情况了,说起来还真是麻烦,还需要考虑那么多因素,重新写一个真心一万个不愿意,或者有人会想到,我们可以直接把BaseActivity布局中的直接复制,贴到BaseFragment的布局,想想也是个方法,可是万一下次再什么地方还需要这个Title布局(虽然我暂时还没想到哪里还会需要),我们还需要去找布局,再复制,对于我这种懒人来说,怎么可能忍得了!
所以就有了上面的标题,那就是Title的封装,你没有看错,布局也是可以封装的,而且也不困难,下面我们就开始。
首先是需要创建一个xml布局,类型当然选择的是Layout,我这里将这个布局很无脑的命名为title_layout,随后将BaseActivity中的Title布局剪切下来粘贴到这个布局中,也就成了这个样子:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="@dimen/title_height"android:background="@color/colorPrimary"><ImageViewandroid:id="@+id/base_back"android:layout_width="50dp"android:layout_height="50dp"android:padding="@dimen/size_13"android:src="@mipmap/back"android:tint="@android:color/white" /><TextViewandroid:id="@+id/base_title"android:layout_width="wrap_content"android:layout_height="match_parent"android:layout_centerInParent="true"android:gravity="center"android:text="@string/title"android:textColor="@android:color/white"android:textSize="@dimen/size_20" /><ImageViewandroid:id="@+id/base_right_icon2"android:layout_width="50dp"android:layout_height="50dp"android:layout_toLeftOf="@+id/base_right_icon1"android:contentDescription="@string/second_function_key"android:padding="@dimen/size_13"android:src="@mipmap/add"android:tint="@android:color/white"android:visibility="gone" /><ImageViewandroid:id="@+id/base_right_icon1"android:layout_width="50dp"android:layout_height="50dp"android:layout_alignParentRight="true"android:contentDescription="@string/first_function_key"android:padding="@dimen/size_13"android:src="@mipmap/more"android:tint="@android:color/white"android:visibility="gone" /><TextViewandroid:id="@+id/base_right_text"android:layout_width="50dp"android:layout_height="50dp"android:layout_alignParentRight="true"android:gravity="center"android:text="@string/make_sure"android:textColor="@android:color/white"android:textSize="@dimen/size_17"android:visibility="gone" />
</RelativeLayout>

可是很显然,剪切下来,那么在BaseActivity中也没有了这个Title布局,这可怎么办呢,下面就让我们见证一下Title疯转的神奇之处吧,在BaseActivity布局之前Title的位置上,写如下的代码:

    <include
            android:id="@+id/base_title_layout"layout="@layout/title_layout"></include>

是不是看到之前被我们剪切的Title布局又重新显示出来了?至于include是什么,怎么用,我这种小菜鸟就不在此多言了,还是直接上链接,大家一起去瞻仰一下大神们是如何讲解的,没错就是我们郭霖郭神的Android最佳性能实践(四)——布局优化技巧。当然,打击可以看到优化的部分除了include还有merge以及ViewStub,大家可以看一下郭神的博客自行理解一下,我这里后面的博客应该也会用到这两部分的优化,不过我这种懒人你们懂的,没用到的时候,怎么可能写到自己的博客里,所以这部分只能在后面随缘讲解了。
好了闲言少叙,搞定了BaseActivity,下面我们也该处理一下BaseFragment中的布局了,不过很好运的是由于Fragment也是在Activity的布局中使用的,所以既然我们的BaseActivity外已经 嵌套了一层ScrollView了,所以BaseFragment的布局中就不再需要多此一举了,我们只需要进行其中的布局即可,代码如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/base_scroll_view"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.banshouweng.mybaseapplication.base.BaseFragment"><include
        android:id="@+id/base_title_layout"layout="@layout/title_layout"></include><LinearLayout
        android:id="@+id/base_main_layout"android:layout_width="match_parent"android:layout_height="0dip"android:layout_weight="1"android:orientation="vertical"></LinearLayout>
</LinearLayout>

是不是看起来要简洁一些,至此我们的Title的封装也就结束了,当然,也就是include的使用罢了。

Title对应的方法

1、初始化控件

这里需要注意的地方是,偷懒的我把initView改成了使用ButterKnife的样子,所以在BaseActivity中的是如下代码:

    /*** 控件初始化*/public void initView() {baseBack = ButterKnife.findById(activity, R.id.base_back);baseRightIcon1 = ButterKnife.findById(activity, R.id.base_right_icon1);baseRightIcon2 = ButterKnife.findById(activity, R.id.base_right_icon2);baseTitle = ButterKnife.findById(activity, R.id.base_title);baseRightText = ButterKnife.findById(activity, R.id.base_right_text);baseTitleLayout = ButterKnife.findById(activity, R.id.base_title_layout);baseMainLayout = ButterKnife.findById(activity, R.id.base_main_layout);baseScrollView = ButterKnife.findById(activity, R.id.base_scroll_view);}

而在BaseFragment切记一定要修改成如下:

    /*** 控件初始化*/private void initView() {baseBack = ButterKnife.findById(currentLayout, R.id.base_back);baseRightIcon1 = ButterKnife.findById(currentLayout, R.id.base_right_icon1);baseRightIcon2 = ButterKnife.findById(currentLayout, R.id.base_right_icon2);baseTitle = ButterKnife.findById(currentLayout, R.id.base_title);baseRightText = ButterKnife.findById(currentLayout, R.id.base_right_text);baseTitleLayout = ButterKnife.findById(currentLayout, R.id.base_title_layout);baseMainLayout = ButterKnife.findById(currentLayout, R.id.base_main_layout);baseScrollView = ButterKnife.findById(currentLayout, R.id.base_scroll_view);}

其中的currentLayout是在onCreateView中保存下来的,这么做的主要原因是,如果这里我们使用的是activity,则表示这些代码我们是让ButterKnife去Fragment所绑定的Activity中去寻找控件,而我们的目的却是让其在当前的Fragment中寻找,所以这里不能使用activity,而需要替换成currentLayout。

2、Title方法封装

所有的控件都已经初始化完成,那么我们也该进行方法的封装了,其实说来说去还是那几个方法而已,我们还是只需要复制过来即可,而其调用的方式也与BaseActivity中封装的方法调用的方式完全相同,所以这部分到此也就结束了。

ps:为了防止结束的太过仓促,在结尾的部分,我还是对BaseActivity做一些补充比较好,那就是在BaseActivity中,我们使用了ScrollView,是为了兼容一些分辨率过低的手机,防止页面内容显示不全,可是有一些页面是没有Title的,例如首页就经常不需要使用Title,而之前我想的是,直接使用setContentView方法,所以就没有做对应的处理,却忽略了如果一旦使用了setContentView方法,那么ScrollView的效果就不在了,所以就又添加了一个隐藏头布局的方法:

    /*** 隐藏头布局*/public void hideTitle() {baseTitleLayout.setVisibility(View.GONE);}

当然,没有确定Fragment中是否需要使用,我们可以先封装到BaseFragment中,也可以等用到时再去封装。

附录

《一个Android工程的从零开始》目录

这篇关于《一个Android工程的从零开始》-6、base(五) BaseFragment封装的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/995125

相关文章

Android 悬浮窗开发示例((动态权限请求 | 前台服务和通知 | 悬浮窗创建 )

《Android悬浮窗开发示例((动态权限请求|前台服务和通知|悬浮窗创建)》本文介绍了Android悬浮窗的实现效果,包括动态权限请求、前台服务和通知的使用,悬浮窗权限需要动态申请并引导... 目录一、悬浮窗 动态权限请求1、动态请求权限2、悬浮窗权限说明3、检查动态权限4、申请动态权限5、权限设置完毕后

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

Go语言利用泛型封装常见的Map操作

《Go语言利用泛型封装常见的Map操作》Go语言在1.18版本中引入了泛型,这是Go语言发展的一个重要里程碑,它极大地增强了语言的表达能力和灵活性,本文将通过泛型实现封装常见的Map操作,感... 目录什么是泛型泛型解决了什么问题Go泛型基于泛型的常见Map操作代码合集总结什么是泛型泛型是一种编程范式,允

Android kotlin语言实现删除文件的解决方案

《Androidkotlin语言实现删除文件的解决方案》:本文主要介绍Androidkotlin语言实现删除文件的解决方案,在项目开发过程中,尤其是需要跨平台协作的项目,那么删除用户指定的文件的... 目录一、前言二、适用环境三、模板内容1.权限申请2.Activity中的模板一、前言在项目开发过程中,尤

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Android WebView的加载超时处理方案

《AndroidWebView的加载超时处理方案》在Android开发中,WebView是一个常用的组件,用于在应用中嵌入网页,然而,当网络状况不佳或页面加载过慢时,用户可能会遇到加载超时的问题,本... 目录引言一、WebView加载超时的原因二、加载超时处理方案1. 使用Handler和Timer进行超

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影