android之fragment活动栈单例
来源:互联网 发布:最新翻墙软件 编辑:程序博客网 时间:2024/06/16 21:47
本文主要记录一些零碎的东西
最近参加了一个做地图的公司的面试,怎么说呢,反正问的我都不会,问题感觉偏向内存的显示优化方向,比如Bitmap占内存大小啦之流,只怪自己学业不精。
项目还要继续,在写项目时,发现fragment的活动栈有些问题,回想起面试官问过这个问题 ,研究一下。
说一下问题的出现,我的fragment,从A--->(transaction.addToBackStack)B--->(transaction.addToBackStack)C--->B--->(transaction.addToBackStack)C,然后在这是按返回按钮,回退到B,再次按回退按钮,界面没有反应,在顶部的导航栏中将当前的布局文件的内容切换成另外一个fragment,没有压入栈,这时就会发现界面上乱套了,两个界面都显示着,新切换的界面在上C界面在下,问题就出现啦。
这里解决也简单,在C--->B是加上transaction.addToBackStack,就没有问题了,但是又会出现一个问题,没有做单例,如果我一直C--->B--->C--->B--->C...活动栈中存在多个重复的B和C对象。
那如何做单例呢,activity里做单例可以在mainfest.xml文件里的activity 里配置android:launchMode,有四个参数
standard 每次都会新建,每个Task都可以有,且每个Task都可以有多个实例(每个Task都可以有,且可以有多个)
singleTop 当前实例如果在栈顶,就不新建实例,调用其OnNewIntent。 如不在栈顶,则新建实例 (每个Task都可以有,且可以有多个,在栈顶时可复用)
singleTask 新建一个Task,如果已经有其他的Task并且包含该实例,那就直接调用那个Task的实例。(只有一个Task中会有)
singleInstance 新建一个Task,且在该Task中只有它的唯一一个实例。 (只有一个Task会有,且该Task中只有它)
但是上面这么好的东西,但是不是我想要的效果,其实我每次C--->B--->C--->B--->C...时数据都是变化的,我想实现的是使用一个对象,但是每次replace时不仅要切换界面,还要更新显示的数据,目前还没有想到很好的解决方案。
- - - - - - - - - - - - - - - - - - - -更新 2016-04-13 - -- - - - - - -- - - - - - - - - - - - -
想着fragment切换时不传数据,把要更新的数据写在一个单独的类中有get/set方法,新的fragment直接get新数据
发现 replace()这个方法只是在上一个Fragment不再需要时采用的简便方法。
正确的切换方式是add(),切换时hide(),add()另一个Fragment;再次切换时,只需hide()当前,show()另一个。
这样就能做到多个Fragment切换不重新实例化,
有点投机取巧的意思,调用onResume方法,但是基本上我实现了返回栈里只有对象的单例的,同时也刷新的fragment上的数据,
看下测试运行结果
上传一张fragment的生命周期
主要代码:
先看看DataUtil,简单模拟一下数据
/** * Created by Administrator on 2016/4/13. */public class DataUtil { public static String getNum() { return (new Random()).nextInt()+""; }}main_activity 布局文件
<?xml version="1.0" encoding="utf-8"?><RelativeLayout 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" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <FrameLayout android:id="@+id/change" android:layout_width="match_parent" android:layout_height="match_parent"></FrameLayout></RelativeLayout>fragment布局文件,
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:background="#0ff" android:id="@+id/show" android:layout_width="match_parent" android:layout_height="100dp" android:textSize="40sp" android:text="111"/></LinearLayout>mainactivity
package android.addre.com.fragmenttest;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentTransaction;import android.os.Bundle;import android.support.v4.app.FragmentActivity;public class MainActivity extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); switchContent(null,FragmetntA.getFragmetntA()); } public void switchContent(Fragment from, Fragment to) { FragmentTransaction transactio = getSupportFragmentManager().beginTransaction(); if (!to.isAdded()) { // 先判断是否被add过,没有添加就添加 if(from != null){ transactio.hide(from); transactio.addToBackStack(null); } transactio.add(R.id.change, to); transactio.commit(); // 隐藏当前的fragment,add下一个到Activity中 } else { if(from != null){ transactio.hide(from); } to.onResume();//这里用户更新数据,不加这句就可以实现单例了,但是不会调用任何生命周期里的方法,不会更新数据 transactio.show(to).commit(); // 隐藏当前的fragment,显示下一个 } }}fragmentA
import android.content.Context;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentTransaction;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by Administrator on 2016/4/13. */public class FragmetntA extends Fragment { private View view; private TextView textView; private static FragmetntA fragmetntA; public static FragmetntA getFragmetntA(){ if(fragmetntA == null){ fragmetntA = new FragmetntA(); } return fragmetntA; } @Override public void onAttach(Context context) { super.onAttach(context); Log.i("slack", "onAttach...A"); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i("slack", "onCreate...A"); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.i("slack", "onCreateView...A"); view = inflater.inflate(R.layout.fragmentlayout, null); textView =(TextView)view.findViewById(R.id.show); view.findViewById(R.id.show).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.i("slack", "onClick...A"); //切换界面 /*FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.change, FragmetntB.getFragmetntB()); transaction.addToBackStack(null); transaction.commit();*/ ((MainActivity)getActivity()).switchContent(fragmetntA, FragmetntB.getFragmetntB()); } }); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.i("slack", "onActivityCreated...A"); } @Override public void onStart() { super.onStart(); Log.i("slack", "onStart...A"); } @Override public void onResume() { super.onResume(); Log.i("slack", "onResume...A"); textView.setText("A:" + DataUtil.getNum()); } @Override public void onPause() { super.onPause(); Log.i("slack", "onPause...A"); } @Override public void onStop() { super.onStop(); Log.i("slack", "onStop...A"); } @Override public void onDestroyView() { super.onDestroyView(); Log.i("slack", "onDestroyView...A"); } @Override public void onDestroy() { super.onDestroy(); Log.i("slack", "onDestroy...A"); } @Override public void onDetach() { super.onDetach(); Log.i("slack", "onDetach...A"); }}
fragmentB
import android.content.Context;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentTransaction;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.TextView;/** * Created by Administrator on 2016/4/13. */public class FragmetntB extends Fragment { private View view; private TextView textView; private static FragmetntB fragmetntB; public static FragmetntB getFragmetntB(){ if(fragmetntB == null){ fragmetntB = new FragmetntB(); } return fragmetntB; } @Override public void onAttach(Context context) { super.onAttach(context); Log.i("slack", "onAttach...B"); } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.i("slack", "onCreate...B"); } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Log.i("slack", "onCreateView...B"); View view = inflater.inflate(R.layout.fragmentlayout,null); textView =(TextView)view.findViewById(R.id.show); view.findViewById(R.id.show).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.i("slack", "onClick...B"); //切换界面 /*FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction().replace(R.id.change, FragmetntA.getFragmetntA()); transaction.addToBackStack(null); transaction.commit();*/ ((MainActivity) getActivity()).switchContent(fragmetntB, FragmetntA.getFragmetntA()); } }); return view; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Log.i("slack", "onActivityCreated...B"); } @Override public void onStart() { super.onStart(); Log.i("slack", "onStart...B"); } @Override public void onResume() { super.onResume(); Log.i("slack", "onResume...B"); textView.setText("B:" + DataUtil.getNum()); } @Override public void onPause() { super.onPause(); Log.i("slack", "onPause...B"); } @Override public void onStop() { super.onStop(); Log.i("slack", "onStop...B"); } @Override public void onDestroyView() { super.onDestroyView(); Log.i("slack", "onDestroyView...B"); } @Override public void onDestroy() { super.onDestroy(); Log.i("slack", "onDestroy...B"); } @Override public void onDetach() { super.onDetach(); Log.i("slack", "onDetach...B"); }}
跳转都写成一个方法,在main_activity里switchContent,参数的意思是当前是显示那个fragment,要显示哪个新的fragment,
添加时先判断一下,要显示的是否已被添加过,未被添加则隐藏当前,添加新的,如果已被添加,则隐藏当前,显示栈里的对应对象
public void switchContent(Fragment from, Fragment to) { FragmentTransaction transactio = getSupportFragmentManager().beginTransaction(); if (!to.isAdded()) { // 先判断是否被add过,没有添加就添加 if(from != null){ transactio.hide(from); transactio.addToBackStack(null); } transactio.add(R.id.change, to); transactio.commit(); // 隐藏当前的fragment,add下一个到Activity中 } else { if(from != null){ transactio.hide(from); } to.onResume();//这里用户更新数据,不加这句就可以实现单例了,但是不会调用任何生命周期里的方法,不会更新数据 transactio.show(to).commit(); // 隐藏当前的fragment,显示下一个 } }如果是已被添加的,在调用show之前先调用resume方法更新一下数据
@Override public void onResume() { super.onResume(); Log.i("slack", "onResume...A"); textView.setText("A:" + DataUtil.getNum()); }
以上就是我的解决方案了,附上测试源码:http://download.csdn.net/detail/i_do_can/9490354
- android之fragment活动栈单例
- android之activity(活动)
- Android之活动
- Android之活动(Activity)
- Android之活动的管理
- Android 活动之启动模式
- Android四大组件之活动
- 【Android】之 活动(Activity)
- Android 四大组件——活动 巧用 Activity 和 Fragment
- android文档之Fragment
- Android昆仑镜之Fragment
- Android之Fragment
- android之Fragment
- Android学习之 Fragment
- android之Fragment
- android之Fragment
- Android之Fragment
- android之Fragment
- HDU 1495(非常可乐)
- 图像处理(图像学习)的基础必备知识
- 前缀 中缀 后缀表达式
- Android应用开发中如何进行单元测试
- Laxcus大数据管理系统2.0(5)- 第三章 数据存取
- android之fragment活动栈单例
- hdu1241
- c++实验2—学生成绩
- 15Knight Moves
- 三个线程轮流输出ABC各十次(另附两个数组找相同的数若干种解法+两个线程轮流循环若干次)
- 用Redis存储Tomcat集群的Session
- 友盟第三方分享入坑笔记(eclipse版)
- 百度地图定位,高德地图定位
- 在myeclipse中快速搭建Struts2框架