我已经看到了两个在应用程序中实例化新Fragment的一般实践:
Fragment newFragment = new MyFragment();
Run Code Online (Sandbox Code Playgroud)
和
Fragment newFragment = MyFragment.newInstance();
Run Code Online (Sandbox Code Playgroud)
第二个选项使用静态方法newInstance(),通常包含以下方法.
public static Fragment newInstance()
{
MyFragment myFragment = new MyFragment();
return myFragment;
}
Run Code Online (Sandbox Code Playgroud)
起初,我认为主要的好处是我可以重载newInstance()方法以在创建Fragment的新实例时提供灵活性 - 但我也可以通过为Fragment创建重载构造函数来实现这一点.
我错过了什么?
一种方法比另一种方法有什么好处?还是只是好习惯?
使用兼容包以使用Fragments定位2.2.
重新编码活动以在应用程序中使用片段后,我无法获得方向更改/状态管理工作,因此我创建了一个带有单个FragmentActivity和单个片段的小型测试应用程序.
方向更改的日志很奇怪,多次调用片段OnCreateView.
我显然缺少一些东西 - 比如分离片段并重新连接它而不是创建一个新实例,但是我看不到任何可以指示我出错的文档.
请问有人能说清楚我在做错了吗.谢谢
方向更改后的日志如下.
Initial creation
12-04 11:57:15.808: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:15.945: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:16.081: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 1
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:57:39.031: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:57:39.031: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:57:39.167: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState null
Orientation Change 2
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.162: D/FragmentTest.FragmentOne(3143): onSaveInstanceState
12-04 11:58:32.361: D/FragmentTest.FragmentTestActivity(3143): onCreate
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView
12-04 11:58:32.361: D/FragmentTest.FragmentOne(3143): OnCreateView->SavedInstanceState not null
12-04 11:58:32.361: …Run Code Online (Sandbox Code Playgroud) 什么究竟,当你调用发生setRetainInstance(true)在Fragment?文档几乎不存在,这似乎是一个非常重要的功能.具体来说,我想知道这个序列(我编造的)有多少是真的:
- 用户旋转设备.
- 该片段从分离
Activity和Fragment.onDetach()被调用.- 活动被摧毁;
Activity.onDestroy()叫做.- 所述
Activityjava对象被删除(如果可能,通过GC).Activity创建一个新的java对象; 它的构造函数,并被onCreate()调用.- 在
Activity.onCreate()我们要么setContentView(...)设置包含片段的布局,要么我们FragmentTransaction用来添加片段.- 我真的不确定这一点,但我认为android很聪明,可以找到旧的片段,并呼吁
Fragment.onAttach()将它重新连接到新的ActivityActivity.onResume()调用下一个(或之前?谁知道?).
那是对的吗?即使我FragmentTransaction.add(new MyFragment(), ...)第一次明确使用,Android是否足够智能找到旧片段?如果是这样,我如何避免添加另一个片段onCreate()?我需要做这样的事吗?:
if (getSupportFragmentManager().findFragmentByTag("foo") == null)
{
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(new FooFragment(), "foo").commit();
}
Run Code Online (Sandbox Code Playgroud) 我发现Fragment #setRetainInstance(true)令人困惑.这是从Android Developer API中提取的Javadoc :
public void setRetainInstance(boolean retain)
控制是否在活动重新创建(例如从配置更改)中保留片段实例.这只能用于不在后栈中的片段.如果设置,则在重新创建活动时,片段生命周期会略有不同:
- onDestroy()不会被调用(但是onDetach()仍然会被调用,因为片段正在与其当前活动分离.
- 因为片段没有被重新创建,所以不会调用onCreate(Bundle).
- onAttach(活动)和onActivityCreated(捆绑)将仍然被调用.
问题:作为开发人员,您如何使用它,为什么它会使事情变得更容易?
Android开发人员指南中有一个关于Fragments使用的不错的部分.使用Fragments的一种方法是没有UI.有一些参考使用它作为后台处理的一种手段,但碎片带给这个领域的优势是什么?在哪里可以选择使用Fragment over Threads,AsyncTasks,Handlers等进行后台处理?
我已经读过,.setOnRetainInstance(true)提供UI的片段设置可能会导致内存泄漏.
有人可以解释为什么以及如何发生这种情况?我没有在任何地方找到详细的解释.
无法实例化片段确保类名存在,是公共的,并且具有公共的空构造函数
是因为我的片段不是静态类吗?是因为我的片段是一个内在阶级?
如果我将Fragment设为静态类,那么我对findViewById的所有引用都会失败,这意味着很多重构.
如何在不将内部Fragment变成静态类的情况下解决这个问题?
我有一个"hello world" - 使用android-support-v4片段API的示例应用程序.该活动包含一个按钮,单击它将显示DialogFragment.但是,即使使用setRetainInstance(true),像旋转这样的配置更改也会导致对话框消失.
知道如何解决这个问题吗?
RetFragment.java
package me.local.HelloFroyo;
import android.os.Bundle;
import android.support.v4.app.*;
import android.util.Log;
import android.view.*;
public class RetFragment extends DialogFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.hello_dialog_fragment, container);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("RET", "onDestroy");
}
}
Run Code Online (Sandbox Code Playgroud)
MainActivity.java
package me.local.HelloFroyo;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
public class MainActivity extends FragmentActivity {
private static final String TAG_DLG = "myFragDlg";
public void onCreate(Bundle …Run Code Online (Sandbox Code Playgroud) 我试图保存片段状态,onSaveInstanceState但当我回到片段时,它总是重新加载而不是从上一个状态开始.
我调查了onCreateView,onActivityCreated它总是onSaveInstanceState为空.
public void navigateFragment(String tag, Fragment fragment,
boolean shouldAdd) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
if (shouldAdd)
mStacks.get(tag).push(fragment); // push fragment on stack
ft.replace(android.R.id.tabcontent, fragment);
if (shouldAdd)
ft.addToBackStack(tag);
ft.commit();
}
Run Code Online (Sandbox Code Playgroud)
由于我无法使用,backstack因为在标签中,堆栈没有用.任何帮助将受到高度赞赏.
我有一个父片段活动,其ViewPager包含一个子ViewPager.子ViewPager包含每个页面的片段.我使用回调接口在这些子页面片段和顶级父片段活动之间进行通信,例如
public interface Callbacks {
public void onItemSelected(Link link);
}
Run Code Online (Sandbox Code Playgroud)
在父片段活动中,我会监听onItemSelected事件,例如
@Override
public void onItemSelected(Link link) {
Bundle argumentsFront = new Bundle();
argumentsFront.putParcelable(FragmentComments.ARG_ITEM_ID, link);
fragmentComments = new FragmentComments();
fragmentComments.setArguments(argumentsFront);
getSupportFragmentManager().beginTransaction().replace(R.id.post_container, fragmentComments).commitAllowingStateLoss();
}
Run Code Online (Sandbox Code Playgroud)
现在,当应用程序首次启动时,此功能正常.
如果您转动设备以更改方向,则活动将重新启动.所有片段在我使用时重新初始化setRetainInstance(true);(我不在子ViewPager的页面片段中调用setRetainInstance(true),因为它不受支持).但是,如果我单击子ViewPager的片段中的列表项,我会得到以下异常:
FATAL EXCEPTION: main
java.lang.IllegalStateException: Activity has been destroyed
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1342)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commitAllowingStateLoss(BackStackRecord.java:578)
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么会这样?
谢谢
android illegalstateexception android-fragments android-viewpager