【问题标题】:How to get the Activity in nested fragments?如何在嵌套片段中获取活动?
【发布时间】:2015-07-09 04:09:30
【问题描述】:

我试图在 ViewPager 中包含的片段中获取调用 getActivity() 的活动,并且此 ViewPager 包含在片段中。我需要在这些片段中调用此活动的一些方法,但 getActivity 始终为这些片段返回 NULL。

我不知道这是否是一个好方法,但我需要视图寻呼机包含的片段根据操作栏操作更新其内容并显示消息说已完成或出现错误。

我们将不胜感激。

代码如下:

内部片段:

    public class ReportSessionsFragment extends ReportPageFragment implements IUpdateView {

    private static final String TAG = ReportSessionsFragment.class.getSimpleName();

    private Sessions fSessions;

    private List<Report> reportList = null;
    private ReportsAdapter adapter = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        settings = ((BaseActivity)getActivity()).settings;
    }

    @Override
    public void onStart() {
        super.onStart();
        setCounter(db.getSessionsCount());

        if(settings.getSelectedRoom() != null){
            reportList = db.getSessionsByRoom(settings.getSelectedRoom().getName(),
                    settings.getStatusSelectedList());
            adapter = new ReportsAdapter(getActivity(), reportList, EReport.Sessions);
            mRecyclerView.setAdapter(adapter);
        }

    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void reload() {
        HashMap<String, Object> parameters = new HashMap<>();
        parameters.put(Fetcher.REQUEST_PARAMETERS, getEventInformation());

        showProgress(getString(R.string.txt_requesting_sessions));
        fSessions = new Sessions(getActivity(), this);
        fSessions.handleSession(parameters, false);
    }

    @Override
    public void delta() {

    }

    @Override
    public void updateProcess(String message) {

    }

    @Override
    public void onProcessEnded(RequestType type, boolean isProvisioningCompleted, String message) {
        reportList = db.getSessionsByRoom(settings.getSelectedRoom().getName(),
                settings.getStatusSelectedList());
        adapter.notifyDataSetChanged();
        hideProgress();
    }

    @Override
    public void onError(Exception e, boolean isProvisioningCompleted) {
        hideProgress();
        showError(getString(R.string.txt_error_title),
                e.getMessage());
    }
}

包含 ViewPager 的片段:

    public class ReportSessionsFragment extends ReportPageFragment implements IUpdateView {

    private static final String TAG = ReportSessionsFragment.class.getSimpleName();

    private Sessions fSessions;

    private List<Report> reportList = null;
    private ReportsAdapter adapter = null;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        settings = ((BaseActivity)getActivity()).settings;
    }

    @Override
    public void onStart() {
        super.onStart();
        setCounter(db.getSessionsCount());

        if(settings.getSelectedRoom() != null){
            reportList = db.getSessionsByRoom(settings.getSelectedRoom().getName(),
                    settings.getStatusSelectedList());
            adapter = new ReportsAdapter(getActivity(), reportList, EReport.Sessions);
            mRecyclerView.setAdapter(adapter);
        }

    }

    @Override
    public void onStop() {
        super.onStop();
    }

    @Override
    public void reload() {
        HashMap<String, Object> parameters = new HashMap<>();
        parameters.put(Fetcher.REQUEST_PARAMETERS, getEventInformation());

        showProgress(getString(R.string.txt_requesting_sessions));
        fSessions = new Sessions(getActivity(), this);
        fSessions.handleSession(parameters, false);
    }

    @Override
    public void delta() {

    }

    @Override
    public void updateProcess(String message) {

    }

    @Override
    public void onProcessEnded(RequestType type, boolean isProvisioningCompleted, String message) {
        reportList = db.getSessionsByRoom(settings.getSelectedRoom().getName(),
                settings.getStatusSelectedList());
        adapter.notifyDataSetChanged();
        hideProgress();
    }

    @Override
    public void onError(Exception e, boolean isProvisioningCompleted) {
        hideProgress();
        showError(getString(R.string.txt_error_title),
                e.getMessage());
    }
}

活动:

    public class ReportsActivity extends BaseActivity implements IReports {

    private static final String TAG = ReportsActivity.class.getSimpleName();

    private ReportsFragment reportFragment;
    private HashMap<Integer, MenuItem> menuReports;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        reportFragment = new ReportsFragment();
        addFragment(reportFragment);
    }

    @Override
    protected void onStart() {
        super.onStart();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.menu_reports, menu);

        menuReports = new HashMap<>();

        for(int index = 0; index < menu.size(); index++ ){
            MenuItem mi = menu.getItem(index);
            menuReports.put(mi.getItemId(), mi);
        }

        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        ReportPageFragment reportPage = (ReportPageFragment)reportFragment.getCurrentReportPage();

        switch (item.getItemId()){
            case R.id.action_reload:
                reportPage.reload();
                break;
            case R.id.action_delta:
                reportPage.delta();
                break;
        }

        return true;
    }

    @Override
    public void displayOptionsByReport(int position) {
        MenuItem miReload = null;
        if(menuReports != null){
             miReload = (MenuItem) menuReports.get(R.id.action_reload);
        }

        switch (position){
            case REPORT_SESSION:
                miReload.setVisible(true);
                break;
            case REPORT_ENROLLMENT:
                miReload.setVisible(true);
                break;
            case REPORT_REGISTRANTS:
                miReload.setVisible(false);
                break;
            case REPORT_ASSOCIATIONS:
                miReload.setVisible(false);
                break;
        }
    }
}

FragmentPagerAdapter:

public class ReportsPagerAdapter extends FragmentStatePagerAdapter {

private Context ctx;

public ReportsPagerAdapter(Context ctx, FragmentManager fm) {
    super(fm);
    this.ctx = ctx;
}

@Override
public Fragment getItem(int position) {
    Fragment fragment = null;

    switch (position){
        case 0:
            fragment = Fragment.instantiate(ctx, ReportSessionsFragment.class.getName());
            break;
        case 1:
            fragment = Fragment.instantiate(ctx, ReportEnrollmentFragment.class.getName());
            break;
        case 2:
            fragment = Fragment.instantiate(ctx, ReportRegistrantsFragment.class.getName());
            break;
        case 3:
            fragment = Fragment.instantiate(ctx, ReportAssociationsFragment.class.getName());
            break;
    }

    return fragment;
}

@Override
public int getCount() {
    String[] reportListNames = ctx.getResources().getStringArray(R.array.reports);
    return reportListNames.length;
}

@Override
public CharSequence getPageTitle(int position) {
    String[] reportListNames = ctx.getResources().getStringArray(R.array.reports);
    return reportListNames[position];
}
}

【问题讨论】:

  • 为什么不直接去掉中间的fragment,直接在Activity中包含ViewPager呢? ReportsFragment 做了什么?真的有必要吗?
  • 嗯,这是我可以做的一件事,但我需要它来处理手机和桌子。因此,当处于横向时,应用程序会显示 2 个片段,其中一个是带有视图寻呼机的片段,现在可以正常工作。当我按下操作栏按钮并且 ViewPager 中的片段无法捕获上下文时,问题就开始了。
  • 我看不出它们在哪里被分离以无法获取上下文。

标签: android android-fragments fragmentstatepageradapter


【解决方案1】:

每个片段,即使是另一个片段的子片段,在添加到片段树时都会收到对onAttach() 的调用。包含片段的活动作为参数传入。最简单的解决方案可能是将活动保存为片段的成员。然后在以后需要时可用。

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    //save the activity to a member of this fragment
    mHostActivity = activity;
}

对于始终位于树中固定深度的片段,另一种方法是根据需要多次使用getParent() 以到达最顶部的片段。例如,在您的分页器片段的子片段中:

getParentFragment().getActivity()

【讨论】:

  • 感谢您的回答,我的问题与我在问题中发布的内容无关,与您回答的内容更相关。每次我将项目放在那个位置时,我都会实例化片段。但是由于您的回答,我检查了 onAttach 并看到它被我的适配器中的 getItem 方法覆盖,我会投票给您的回答,因为它让我思考了一下(一天半的时间寻找想法)并找到了解决方案我的问题。
  • onAttach(activity) 在 android.support.v4.app.Fragment 中已弃用。使用 getActivity() 似乎是一个更好的选择。
  • @Dusko 澄清您的评论:onAttach(Activity) 在 API 级别 23 中已弃用并由 onAttach(Context) 取代。
  • @qbix 是的,我看到了。您可以在上下文中使用类强制转换,但我将其包含在 if-case 检查 isinstanceof 中,因为正如其他人所提到的,上下文可能不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-17
  • 2023-03-12
相关资源
最近更新 更多