您的位置:首页 > 移动开发 > Android开发

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,简单模拟一下数据

/**
* 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: