Android使用Fragment打造万能页面切换框架

作者:襄阳西继迅达电梯有限公司  发布时间:2017-09-11 14:25:27
Android使用Fragment打造万能页面切换框架

首先我们来回忆一下传统用Activity进行的页面切换,activity之间切换,首先需要新建intent对象,给该对象设置一些必须的参数,然后调用startActivity方法进行页面跳转。如果需要activity返回结果,则调用startActivityForResult方法,在onActivityResult方法中获得返回结果。此外,每一个要展示的activity需要在AndroidManifest.xml文件中注册。而且,如果在某些特定的情况下(比如65536方法数爆炸)要动态加载dex,还得手动管理activity的生命周期。那么,有没有这么一种方法进行页面切换时,无需在AndroidManifest.xml文件中声明这些信息,动态加载时又无需我们管理生命周期,等等优点呢。

我们来回忆一下,在android3.0之后,谷歌出了一个Fragment,这个东西依赖于activity,其生命周期由宿主activity进行管理,并且可以通过FragmentManager和FragmentTransaction等相关的类进行管理。那么我们能不能从Fragment入手,打造一个完全由Fragment组成的页面跳转框架呢。

使用Fragment其实很简单,首先开启一个事务,通过add,replace,remove等方法进行添加,替换,移除等操作,这一切的操作可能需要依赖一个容器,这个容器提供一个id,进行对应操作时将这个id作为参数传入。之后通过相应方法提交事务就可以了,就像这样子。

FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.replace(R.id.fragment_container, fragment); fragmentTransaction.commit();

然而我相信你一定有这样的经历,在使用Fragment进行页面切换时又得不断用代码控制其显示与隐藏的逻辑,那么有没有这样一种方法在程序中不断复用这段代码呢?

首先,我们希望Fragment能像Activity那样,进行正确的跳转。那么需要什么,答案是Fragment对象,我们肯定需要它的Class全类名,当然跳转的时候可能会带上一些参数,这个参数应该通过Bundle进行传递。而且,全类名可能太长,不便记忆,我们参考web的架构,应该还要取一个别名alias。就这样,一个Fragment页面的三个基本属性就被我们抽取出来了,组成了如下的实体类。在这个实体类中,页面传递的参数为json形式的String字符串对象,在需要使用的时候我们通过该json构造出bundle。页面名变量mName是整个程序唯一标示该页面的参数,其值唯一,但是其对应的class全类名可以不唯一,也就是说从name到class的映射可以一对多。

public class CorePage implements Serializable { private static final long serialVersionUID = 3736359137726536495L; private String mName; //页面名 private String mClazz; //页面class private String mParams; //传入参数,json object结构 public CorePage(String name, String clazz, String params) { mName = name; mClazz = clazz; mParams = params; } public String getClazz() { return mClazz; } public void setClazz(String clazz) { mClazz = clazz; } public String getName() { return mName; } public void setName(String name) { mName = name; } public String getParams() { return mParams; } public void setParams(String params) { mParams = params; } @Override public String toString() { return Page{ + mName=' + mName + ''' + , mClazz=' + mClazz + ''' + , mParams=' + mParams + ''' + '}'; } }

实体类编写好了,为了更方便的进行页面跳转,我们需要像Activity那样,有一个配置文件,里面存着Fragment名到其全类名的映射关系。那么这些数据存在哪呢。我们参考网络数据,一般从网络上获取的数据有两种格式,一种是json,一种是xml,json由于其优点,在网络传输中被大量使用,这里,我们优先使用json,选定了json之后,就要选定一个json解析的框架,我们不使用android系统自带的,我们使用阿里的fastjson,当然你也可以使用gson或者jackson。我们的Fragment有很多,所以这个Fragment的配置文件应该是一个json数组。就像这个样子

[ { name: test1, class: cn.edu.zafu.corepage.sample.TestFragment1, params: { param1: value1, param2: value2 } }, { name: test2, class: cn.edu.zafu.corepage.sample.TestFragment2, params: } ]

有了这个配置,我们就要在程序进入时读取这个配置。我们将这个配置放在assets目录下,当然你也可以放在其他目录下,只有你能读取到就行,甚至你可以放在压缩包里。然而,实际情况下,这个文件不应该暴露,因为一旦暴露就存在风险。因此,大家可以采用更安全的方式存这些数据,比如把数据压缩到压缩包中,增加一个密码,而读取文件的内容的代码我们移到native中取实现,毕竟java层太容易被反编译了,而c/c++层相对来说会毕竟有难度。

这里为了简单,我们暂时放在assets目录下,那么要从assets目录中读取这个文件内容就必须有这么一个读取该目录下文件的函数,该目录在android中也算是一个比较特殊的目录了,可以通过getAssets()函数,然后获得一个输入流,将文件内容读出,然后将对应的json解析出来就可以了。

/** * 从assets目录下读取文件 * * @param context 上下文 * @param fileName 文件名 * @return */ private String readFileFromAssets(Context context, String fileName) { String result = ; try { InputStreamReader inputReader = new InputStreamReader(context.getResources().getAssets().open(fileName)); BufferedReader bufReader = new BufferedReader(inputReader); String line = ; while ((line = bufReader.readLine()) != null) result += line; } catch (Exception e) { e.printStackTrace(); } return result; }

然后根据该文件内容读取json配置。读取出来后需要将这些数据保存下来。因此要有一个数据结构来保存这个对象,存完之后还要方便取出,存取的依据应该是Fragment的表示,即前面提到的name,因此Map这个数据结构是最适合不过了。

private Map mPageMap = new HashMap(); //保存page的map

将配置读取出来存进该map,读取的时候判断name和class是否为空,为空则跳过。

/** * 从配置文件中读取page */ private void readConfig() { Log.d(TAG, readConfig from json); String content = readFileFromAssets(mContext, page.json); JSONArray jsonArray = JSON.parseArray(content); Iterator

企业建站2800元起,携手武汉肥猫科技,做一个有见地的颜值派!更多优惠请戳:咸宁网站建设 http://xianning.45qun.com

  • 上一篇:php获取数组的最后一个元素
  • 下一篇:最后一页
  •