android之fragment活动栈单例
2016-04-13 22:07
666 查看
本文主要记录一些零碎的东西
最近参加了一个做地图的公司的面试,怎么说呢,反正问的我都不会,问题感觉偏向内存的显示优化方向,比如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,简单模拟一下数据
fragmentB
跳转都写成一个方法,在main_activity里switchContent,参数的意思是当前是显示那个fragment,要显示哪个新的fragment,
添加时先判断一下,要显示的是否已被添加过,未被添加则隐藏当前,添加新的,如果已被添加,则隐藏当前,显示栈里的对应对象
以上就是我的解决方案了,附上测试源码:http://download.csdn.net/detail/i_do_can/9490354
最近参加了一个做地图的公司的面试,怎么说呢,反正问的我都不会,问题感觉偏向内存的显示优化方向,比如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 SDK,ADT,以及API的理解
- [Android开发教程]Android官网developer training中文版教程 - 1.1.1 创建一个Android项目
- 一个简易的下拉刷新Layout
- [置顶] Android studio 升级,完美更新到官方最新稳定版本
- Android版股票K线图实现方案
- 退出Compass时闪现其他界面问题分析
- Android 5.0 Intercept HomeKey
- Android--view自定义--彩虹桥<跑马灯>
- [android] 手机卫士读取联系人
- Android Fragment
- Android dos命令查看应用内存占用情况
- Android移动应用开发中常见的经验技巧总结
- Android多线程断点续传下载
- Ubuntu14.04编译Android FFmpeg详细教程
- android--View自定义基础
- Socket原理的简单理解
- Android-view自定义-Canvas
- 【ANDROID游戏开发二十四】360°平滑游戏摇杆(触屏方向导航)
- 在Android Studio中导入github上的项目
- android socket基于mina框架实现和服务器长连接