【问题标题】:Access Fragment in Activity?在活动中访问片段?
【发布时间】:2015-04-13 09:06:38
【问题描述】:

我有一个包含 2 个片段的主要活动。两个片段都有一个ListView。我想更新MainActivity 中的列表。有没有办法在不将适配器设置为静态适配器的情况下访问活动中的片段列表适配器。 目前我在Mainactivity.java做这样的事情@

public void updatelist() {
  if(fragmentstate=0)
    Fragment1.adapter.notifyDataSetChanged();
  else
    Fragment2.adapter.notifyDataSetChanged();

}

【问题讨论】:

标签: android android-fragments android-listview


【解决方案1】:

您可以使用 Otto 事件总线执行以下操作:

public class UpdateListEvent {
    private int fragmentState;

    public UpdateListEvent(int fragmentState) {
        this.fragmentState = fragmentState;
    }
}

public class MainActivity extends ActionBarActivity {
    ...
    public void updatelist() {
       SingletonBus.INSTANCE.getBus().post(new UpdateListEvent(fragmentState));
    }
}

public class FragmentA extends Fragment {
    @Override
    public void onResume() {
        super.onResume();
        SingletonBus.INSTANCE.getBus().register(this);
    }

    @Override
    public void onPause() {
        SingletonBus.INSTANCE.getBus().unregister(this);
        super.onPause();
    }

    @Subscribe
    public void onUpdateListEvent(UpdateListEvent e) {
        if(e.getFragmentState() == 0) { //is this even necessary?
            this.adapter.notifyDataSetChanged();
        }
    }
}

public class FragmentB extends Fragment {
    @Override
    public void onResume() {
        super.onResume();
        SingletonBus.INSTANCE.getBus().register(this);
    }

    @Override
    public void onPause() {
        SingletonBus.INSTANCE.getBus().unregister(this);
        super.onPause();
    }

    @Subscribe
    public void onUpdateListEvent(UpdateListEvent e) {
        if(e.getFragmentState() != 0) { //is this even necessary?
             this.adapter.notifyDataSetChanged();
        }
    }
}

以及单例总线的修订版

public enum SingletonBus {
    INSTANCE;

    private static String TAG = SingletonBus.class.getSimpleName();

    private Bus bus;

    private volatile boolean paused;

    private final Vector<Object> eventQueueBuffer = new Vector<>();

    private Handler handler = new Handler(Looper.getMainLooper());

    private SingletonBus() {
        this.bus = new Bus(ThreadEnforcer.ANY);
    }

    public <T> void postToSameThread(final T event) {
        bus.post(event);
    }

    public <T> void postToMainThread(final T event) {
        try {
            if(paused) {
                eventQueueBuffer.add(event);
            } else {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            bus.post(event);
                        } catch(Exception e) {
                            Log.e(TAG, "POST TO MAIN THREAD: BUS LEVEL");
                            throw e;
                        }
                    }
                });
            }
        } catch(Exception e) {
            Log.e(TAG, "POST TO MAIN THREAD: HANDLER LEVEL");
            throw e;
        }
    }

    public <T> void register(T subscriber) {
        bus.register(subscriber);
    }

    public <T> void unregister(T subscriber) {
        bus.unregister(subscriber);
    }

    public boolean isPaused() {
        return paused;
    }

    public void setPaused(boolean paused) {
        this.paused = paused;
        if(!paused) {
            Iterator<Object> eventIterator = eventQueueBuffer.iterator();
            while(eventIterator.hasNext()) {
                Object event = eventIterator.next();
                postToMainThread(event);
                eventIterator.remove();
            }
        }
    }
}

【讨论】:

  • 但是,如果这只是一个跟踪哪个片段当前处于活动状态的问题,那么这是矫枉过正的。或者至少,fragmentState 是否必要?我不这么认为。毕竟,片段只有在它们处于活动状态时才会收到事件。
  • 我希望我可以使用 otto。但我不能。
  • 哦。太糟糕了。 LocalBroadcastManager 可以作为穷人的奥托。
  • 请注意,Otto您发布活动的同一线程上提供活动。
  • onPause() 中调用setPaused(true) 并在onPostCreate() 中调用setPaused(false)
【解决方案2】:

不要使用静态适配器。有更好(更安全)的方法可以从它的父级 Activity 访问您的片段。

我假设您使用以下方式动态添加片段:

FragmentManager fragmentManager = getFragmentManager();
fragmentManager
              .beginTransaction()
              .add(R.id.fragment_container, new FragmentOne())
              .commit();

片段二也一样。

为了引用那些Fragment,您需要在创建它们时添加一个标签。很简单,只需在现有代码中添加一行即可:

FragmentManager fragmentManager = getFragmentManager();
fragmentManager
              .beginTransaction()
              .add(R.id.fragment_container, new FragmentOne(), "fragmentOneTag")
              .commit();

然后,每当您想获取片段时,请执行以下操作:

FragmentManager fragmentManager = getFragmentManager();
FragmentOne fragmentOne = fragmentManager.getFragmentByTag("fragmentOneTag");

fragmentOne.refreshList();      //Define this method in your class and from there refresh your list

就是这样

【讨论】:

  • 我想知道getFragmentByTag("fragmentOneTag")是否会比使用static访问适配器更影响性能
  • refreshList() 不是静态的。 getFragmentByTag 返回对请求片段的引用,以便您可以访问它的公共方法
【解决方案3】:

如果您只想更新片段列表,则不必访问 adpaters。您可以在 Fragment 上注册本地广播,并从 MainActivity 发送本地广播消息。

来自片段,

LocalBroadcastManager.getInstance(getContext()).registerReceiver(...);

来自 MainActivity,

LocalBroadcastManager.getInstance(getContext()).sendBroadcast(...)

【讨论】:

  • 你为什么要这样做?所有Fragments 必须附加到一个Activity,它首先创建并添加了Fragments。所有Activity 所要做的就是在相关的Fragment 引用上调用public 方法。
  • @Benrad Kim 你是对的。一切都进入单一活动。我为什么要广播?
【解决方案4】:

有没有办法在不将适配器设置为静态适配器的情况下访问活动中的片段列表适配器。

是的。 Fragments 的设计指南允许他们公开public 方法,这些方法可以从他们所附加的Activity 中调用。只需在每个 Fragment 中创建一个方法,然后调用您需要的任何一个。

Activity 应该持有对其创建的任何Fragments 的引用。只需让 Fragment 方法更新它们自己的适配器即可。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-30
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 1970-01-01
    相关资源
    最近更新 更多