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









0 0
原创粉丝点击