Java 如何保存和重用相同的片段实例?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19614300/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to save and reuse same instance of fragments?
提问by Naveed
I have recently started using fragments have created a demo app which looks like this:
我最近开始使用片段创建了一个演示应用程序,如下所示:
Clicking on each button switches between fragment 1, Fragment 2, and Fragment 3.
单击每个按钮可在片段 1、片段 2 和片段 3 之间切换。
What I am trying to accomplish is to only have 1 instance of each Fragment and reuse that. (Please note that all the fragments are created and added dynamically). Currently I am doing this by creating a HashMap of fragment and placing each instance and grabbing it from there.
我想要完成的是每个 Fragment 只有 1 个实例并重用它。(请注意,所有片段都是动态创建和添加的)。目前我通过创建片段的 HashMap 并放置每个实例并从那里抓取它来做到这一点。
So my questions are:
Is there a better way of doing this:
By using FragmentManager's putFragment(...) method? putFragment (Bundle bundle, String key, Fragment fragment)
I can't figure out how to use it in my case. If anyone can give me an example of how to use this method.
所以我的问题是:有没有更好的方法来做到这一点:通过使用 FragmentManager 的 putFragment(...) 方法?putFragment (Bundle bundle, String key, Fragment fragment)
我无法弄清楚如何在我的情况下使用它。如果有人能给我一个如何使用这种方法的例子。
Is it expensive to hold onto a reference of each fragment in my activity? Does this keep all the fragments alive? I am using soft reference to tackle this but I am not sure if this is the proper way of doing this. Please point me towards any alternative way of doing this or let me know if this is best way to accomplish this.
在我的活动中保留每个片段的引用是否昂贵?这会让所有碎片保持活力吗?我正在使用软引用来解决这个问题,但我不确定这是否是这样做的正确方法。请向我指出这样做的任何替代方法,或者让我知道这是否是实现此目的的最佳方法。
Thanks in advance.
提前致谢。
Here is my code:
这是我的代码:
UPDATE: I am trying to reuse fragments from the back stack, trying to only add them if it does not exists in the back stack. The code below gives me the Illegal state exception after I navigate away from fragment one -> come back to it -> then try to press back button:
更新:我正在尝试重用后端堆栈中的片段,尝试仅在后端堆栈中不存在它们时才添加它们。在我离开片段一之后,下面的代码给了我非法状态异常 -> 回到它 -> 然后尝试按下后退按钮:
10-28 13:21:40.255: ERROR/MessageQueue-JNI(3548): java.lang.IllegalStateException: Fragment already added: FragmentOne{423db570 #0 id=0x7f050006 fragOne}
public class MainActivity extends Activity implements View.OnClickListener {
private Button btnOne;
private Button btnTwo;
private Button btnThree;
/* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initialize();
if(findViewById(R.id.fl) != null){
if(savedInstanceState != null)
return;
}
FragmentManager.enableDebugLogging(true);
updateView("fragOne");
}
private void initialize(){
btnOne = (Button) findViewById(R.id.button1);
btnTwo = (Button) findViewById(R.id.button2);
btnThree = (Button) findViewById(R.id.button3);
btnOne.setOnClickListener(this);
btnTwo.setOnClickListener(this);
btnThree.setOnClickListener(this);
fragHolder = new HashMap<String, SoftReference<Fragment>>();
}
private void updateView(String tag){
FragmentTransaction ft = getFragmentManager().beginTransaction();
Fragment frag = getFragmentManager().findFragmentByTag(tag);
boolean addToStack = true;
if(frag == null){
if(tag.equals("fragOne"))
frag = new FragmentOne();
else if(tag.equals("fragTwo"))
frag = new FragmentTwo();
else if(tag.equals("fragThree"))
frag = new FragmentThree();
}else{
//Don't add to back stack
addToStack = false;
}
ft.replace(R.id.fl, frag, tag);
if(addToStack)
ft.addToBackStack(null);
ft.commit();
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.button1:
updateView("fragOne");
break;
case R.id.button2:
updateView("fragTwo");
break;
case R.id.button3:
updateView("fragThree");
break;
}
}
}
采纳答案by Andrew Schuster
To demonstrate a FragmentTransaction
, the following sample might be helpful to you.
为了演示FragmentTransaction
,以下示例可能对您有所帮助。
First, you want to do all your initialization stuff in the onCreate()
of your activity, which you have right, but we'll make a few changes.
首先,您想在onCreate()
您的 Activity 中完成所有初始化工作,您有权这样做,但我们将进行一些更改。
public class MainActivity extends Activity implements View.OnClickListener {
private Button btnOne;
private Button btnTwo;
private Button btnThree;
/* Called when the activity is first created.*/
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initialize();
if(findViewById(R.id.fl) != null)
{
if(savedInstanceState != null)
{
FragmentTransaction trans = getFragmentManager().beginTransaction();
//This is where we add our first fragment
trans.add(R.id.fl, new FragmentOne());
trans.commit();
}
}
}
private void initialize()
{
btnOne = (Button) findViewById(R.id.button1);
btnTwo = (Button) findViewById(R.id.button2);
btnThree = (Button) findViewById(R.id.button3);
btnOne.setOnClickListener(this);
btnTwo.setOnClickListener(this);
btnThree.setOnClickListener(this);
}
public void onClick(View view)
{
//Here is where we'll actually transfer the fragments
FragmentTransaction trans = getFragmentManager().beginTransaction();
switch(v.getId()){
case R.id.button1:
trans.replace(R.id.fl, new FragmentOne());
trans.addToBackStack(null);
trans.commit();
break;
case R.id.button2:
trans.replace(R.id.fl, new FragmentTwo());
trans.addToBackStack(null);
trans.commit();
break;
case R.id.button3:
trans.replace(R.id.fl, new FragmentThree());
trans.addToBackStack(null);
trans.commit();
break;
}
}
This will allow you to easily transition from one Fragment to the next.
这将使您能够轻松地从一个 Fragment 过渡到下一个 Fragment。
回答by znat
The FragmentManager does it's own memory management. It will kill/recreate or keep in memory your instances according to its logic. You can ensure your fragment's state is save using onSaveInstanceState()
FragmentManager 进行自己的内存管理。它将根据其逻辑杀死/重新创建或保留您的实例。您可以使用以下方法确保片段的状态已保存onSaveInstanceState()
Or you can for force the system to keep your instance alive using setRetainInstance(true)
on your Fragment.
或者您可以强制系统setRetainInstance(true)
在您的 Fragment 上保持您的实例处于活动状态。
This is how you create a transaction.
这就是您创建交易的方式。
FragmentTransaction fragmentTransaction = context.getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.layout, new MyFragment(), f.getClass().getName());
fragmentTransaction.commit();