在片段中使用上下文的最佳方式
best way to use context in fragment
我正在我的应用程序中使用片段。我创建了一个名为 BaseFragment 的 Parent Class,所有其他片段都扩展了这个 Basefragment 下面是这个 Basefragment
的片段
BaseFragment.java
public class BaseFragment extends Fragment {
public MainActivity activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (activity == null && context instanceof MainActivity) {
activity = (MainActivity) context;
}
}
}
public void replaceFragment(Fragment fragment, FragmentDetail last) {
fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
boolean push = true;
if (Validator.isNotNull(last)) {
push = false;
}
/*if(Validator.isNull(last)){
transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right);
}else{
transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left);
}*/
transaction.add(R.id.frame_container, fragment, fragment.getClass().getName());
if (Validator.isNull(last) && preferences.getFragmentStack().size() > 0) {
last = preferences.getFragmentStack().lastElement();
}
if (Validator.isNotNull(last)) {
Fragment f = fragmentManager.findFragmentByTag(last.className);
if (Validator.isNotNull(f)) {
f.onPause();
transaction.remove(f);
}
}
last = new FragmentDetail(fragment.getClass().getName(), getTitle().toString(), preferences.isBack());
if (preferences.isBack() || preferences.getFragmentStack().size() == 0) {
if (push) {
preferences.getFragmentStack().push(last);
}
} else {
while (preferences.getFragmentStack().size() > 1) {
preferences.getFragmentStack().pop();
}
if (!preferences.getFragmentStack().lastElement().className.equals(last.className)) {
preferences.getFragmentStack().push(last);
}
}
transaction.commitAllowingStateLoss();
changeNavigationIcon();
// HWUtil.showToast(这个, fragmentManager.getBackStackEntryCount() + "");
}
并且在我使用 activity 作为上下文的所有其他片段中,我的问题是以这种方式访问上下文的方法是否不好,或者它是否会创建内存 leak.or 任何其他访问方法上下文..任何帮助都适用。
最好的方法是在片段中使用 getActivity() 函数来访问上下文,
因为它将 return 附加片段的 activity 的实例。
使用 getActivity()
是获取父级 activity 上下文的简单快捷方式,但当该片段分离时就会出现问题。
所以在 fragment 中像这样使用它,imo,将满足以更好的方式做它的需要....
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mContext=activity;
}
我认为您存储 context
的方式确实是最佳的,因为您将能够在每个子片段实例中使用它。因为 MainActivity
是片段中的一个实例变量,所以当片段被销毁时它将被垃圾回收。如果我没有弄错 Activity-Fragment 生命周期,当你的 activity 被轮换时,新的片段将被创建,旧的片段实例将被销毁。所以,我们在那里也很好。但是,您需要注意上下文变量声明:
public MainActivity activity;
这使得它可以从任何地方访问。任何 class 都可以调用 context = fragIns.activity
之类的东西并将其保存在那里。这对你来说真的很糟糕,因为现在它持有对该上下文变量的引用。现在,当您的片段不再需要时,它不会被垃圾回收,因为其他 class 持有对其变量之一的引用。你会发现自己在 "memory leak town".
确保您妥善保存此变量并且其引用不会传递给其他 classes。因为,它在超级 class 中,您可以将其定义为:
protected MainActivity activity;
这应该可以完成工作。
我的方式:
public class AppManager extends Application {
private static AppManager mApp;
@Override
public void onCreate() {
super.onCreate();
mApp = this;
}
public static Context getContext() {
return mApp.getApplicationContext();
}
}
所以,任何人都想获得 Context
,只需使用 AppManager.getContext()
,除了开始 Activity
。很简单。
按照你的方式,如果activity重新启动,片段会自动重新创建。在你不处理Activty重启的动作,有可能Activity有两个相同的Fragment,而自动创建的没有调用OnAttch()
,会导致NullPointerException
.
我的解决方案:
public abstract class BaseTabActivity extends BaseActivity {
@CallSuper
protected void initTabs(boolean isRestarted) {
if (isRestarted) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
if (manager.getFragments() == null)
return;
Stream.of(manager.getFragments())
.forEach((fragment) -> {
if (fragment != null)
transaction.remove(fragment);
});
transaction.commit();
manager.executePendingTransactions();
}
}
public FragmentTransaction getSlideAnimTransaction() {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_out_left);
return transaction;
}
}
为避免内存问题,建议您在使用 onAttach(Context context)
时也应使用 onDetach()
:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (activity == null && context instanceof MainActivity) {
activity = (MainActivity) context;
}
}
@Override
public void onDetach() {
this.activity = null;
super.onDetach();
}
我正在我的应用程序中使用片段。我创建了一个名为 BaseFragment 的 Parent Class,所有其他片段都扩展了这个 Basefragment 下面是这个 Basefragment
的片段BaseFragment.java
public class BaseFragment extends Fragment {
public MainActivity activity;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (activity == null && context instanceof MainActivity) {
activity = (MainActivity) context;
}
}
}
public void replaceFragment(Fragment fragment, FragmentDetail last) {
fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
boolean push = true;
if (Validator.isNotNull(last)) {
push = false;
}
/*if(Validator.isNull(last)){
transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right);
}else{
transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left);
}*/
transaction.add(R.id.frame_container, fragment, fragment.getClass().getName());
if (Validator.isNull(last) && preferences.getFragmentStack().size() > 0) {
last = preferences.getFragmentStack().lastElement();
}
if (Validator.isNotNull(last)) {
Fragment f = fragmentManager.findFragmentByTag(last.className);
if (Validator.isNotNull(f)) {
f.onPause();
transaction.remove(f);
}
}
last = new FragmentDetail(fragment.getClass().getName(), getTitle().toString(), preferences.isBack());
if (preferences.isBack() || preferences.getFragmentStack().size() == 0) {
if (push) {
preferences.getFragmentStack().push(last);
}
} else {
while (preferences.getFragmentStack().size() > 1) {
preferences.getFragmentStack().pop();
}
if (!preferences.getFragmentStack().lastElement().className.equals(last.className)) {
preferences.getFragmentStack().push(last);
}
}
transaction.commitAllowingStateLoss();
changeNavigationIcon();
// HWUtil.showToast(这个, fragmentManager.getBackStackEntryCount() + ""); }
并且在我使用 activity 作为上下文的所有其他片段中,我的问题是以这种方式访问上下文的方法是否不好,或者它是否会创建内存 leak.or 任何其他访问方法上下文..任何帮助都适用。
最好的方法是在片段中使用 getActivity() 函数来访问上下文, 因为它将 return 附加片段的 activity 的实例。
使用 getActivity()
是获取父级 activity 上下文的简单快捷方式,但当该片段分离时就会出现问题。
所以在 fragment 中像这样使用它,imo,将满足以更好的方式做它的需要....
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mContext=activity;
}
我认为您存储 context
的方式确实是最佳的,因为您将能够在每个子片段实例中使用它。因为 MainActivity
是片段中的一个实例变量,所以当片段被销毁时它将被垃圾回收。如果我没有弄错 Activity-Fragment 生命周期,当你的 activity 被轮换时,新的片段将被创建,旧的片段实例将被销毁。所以,我们在那里也很好。但是,您需要注意上下文变量声明:
public MainActivity activity;
这使得它可以从任何地方访问。任何 class 都可以调用 context = fragIns.activity
之类的东西并将其保存在那里。这对你来说真的很糟糕,因为现在它持有对该上下文变量的引用。现在,当您的片段不再需要时,它不会被垃圾回收,因为其他 class 持有对其变量之一的引用。你会发现自己在 "memory leak town".
确保您妥善保存此变量并且其引用不会传递给其他 classes。因为,它在超级 class 中,您可以将其定义为:
protected MainActivity activity;
这应该可以完成工作。
我的方式:
public class AppManager extends Application {
private static AppManager mApp;
@Override
public void onCreate() {
super.onCreate();
mApp = this;
}
public static Context getContext() {
return mApp.getApplicationContext();
}
}
所以,任何人都想获得 Context
,只需使用 AppManager.getContext()
,除了开始 Activity
。很简单。
按照你的方式,如果activity重新启动,片段会自动重新创建。在你不处理Activty重启的动作,有可能Activity有两个相同的Fragment,而自动创建的没有调用OnAttch()
,会导致NullPointerException
.
我的解决方案:
public abstract class BaseTabActivity extends BaseActivity {
@CallSuper
protected void initTabs(boolean isRestarted) {
if (isRestarted) {
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
if (manager.getFragments() == null)
return;
Stream.of(manager.getFragments())
.forEach((fragment) -> {
if (fragment != null)
transaction.remove(fragment);
});
transaction.commit();
manager.executePendingTransactions();
}
}
public FragmentTransaction getSlideAnimTransaction() {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.anim.slide_from_right, R.anim.slide_out_left);
return transaction;
}
}
为避免内存问题,建议您在使用 onAttach(Context context)
时也应使用 onDetach()
:
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (activity == null && context instanceof MainActivity) {
activity = (MainActivity) context;
}
}
@Override
public void onDetach() {
this.activity = null;
super.onDetach();
}