在片段中使用上下文的最佳方法

时间:2016-08-06 05:22:00

标签: android fragment android-context

我在我的应用程序中使用片段。我创建了一个名为BaseFragment的父类,所有其他片段扩展了这个Basefrgment,下面是这个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(this,fragmentManager.getBackStackEntryCount()+“”);     }

并且在使用activity作为上下文的所有其他片段中,我的问题是以这种方式访问​​上下文是否是坏方法,或者它是否会创建内存泄漏。或者任何其他访问上下文的方法。任何帮助都是适用的。

5 个答案:

答案 0 :(得分:1)

最好的方法是在片段内使用getActivity()函数来访问上下文, 因为它将返回附加了片段的活动的实例。

答案 1 :(得分:1)

使用getActivity()可以轻松快捷地获取父活动的上下文,但在分离该片段时会出现问题。

所以在片段内部使用它,imo,就足以满足更好的方式....

@Override
public void onAttach(Activity activity) {        
    super.onAttach(activity);
    mContext=activity;
}

答案 2 :(得分:1)

我认为存储context的方式非常合理,因为您可以在每个子片段实例中使用它。因为MainActivity是片段中的实例变量,所以当片段被破坏时,它将被垃圾收集。如果我没有弄错Activity-Fragment生命周期,当你的活动被轮换时,将创建新的片段并且旧的片段实例将被销毁。所以,我们也很好。但是,您需要注意上下文变量声明:

public MainActivity activity;

这使它可以从任何地方访问。任何类都可以调用context = fragIns.activity之类的东西并保存在那里。这对你来说真的很糟糕,因为它现在拥有对该上下文变量的引用。现在,当不再需要您的片段时,它将不会被垃圾收集,因为其他一些类正在持有对其变量之一的引用。你会发现自己处于“记忆泄漏之城”。

确保你持有这个变量,并且它的引用不会传递给其他类。因为,它在超类中,您可以将其定义为:

protected MainActivity activity;

这应该可以胜任。

答案 3 :(得分:1)

为避免内存问题,建议您每次使用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();
}

答案 4 :(得分:0)

我的方式:

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。这很简单。

按照您的方式,如果活动重新启动,则片段将再次自动创建。在你没有处理Activty重启动作的情况下,活动有两个相同的片段,而自动创建的片段没有调用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;
    }

}