ViewPager用于通知特定事件的片段的活动

时间:2012-01-21 21:22:12

标签: android fragment android-viewpager

我有一个ViewPager,它正在使用FragmentAdapter来显示相同​​类型的多个片段。虽然这些片段基本上是从同一个类实例化的,但它们使用ListView来显示不同的信息。 (显然ListViewArrayAdapter所包围。) 后台服务也在运行,并且不断从Internet接收数据。我希望能够在我的后台服务通知我特定事件时更新ViewPager中的特定片段。
我怎样才能做到这一点? 我们非常感谢您的代码片段!

(顺便说一下,我看到this similar question,但我不知道如何使用他们的建议!)

更简单: 我使用ViewPager的活动:
[片段0] [片段1] [片段2]

后台服务告诉我(通过广播)更新片段1 中的ListView

修改 以下是示例代码:

public class ChatWindowPager extends FragmentActivity
{
    private ViewPager mViewPager = null;
    private ChatFragmentAdapter mAdapter = null;
    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.chat_window_pager);

        this.mViewPager = (ViewPager) findViewById(R.id.chatPager);
        this.mAdapter = new ChatFragmentAdapter(getSupportFragmentManager());
        this.mViewPager.setAdapter(this.mAdapter);
        .
        .
        .
    }

    class ChatFragmentAdapter extends FragmentPagerAdapter implements ViewProvider
    {

        public ChatFragmentAdapter(final FragmentManager fm)
        {
            super(fm);
        }

        @Override
        public Fragment getItem(final int arg0)
        {
            String friendId = ..... // Some initializations
            ChatWindowFragment f = ChatWindowFragment.newInstance(friendId);
            return f;
        }

        @Override
        public int getCount()
        {
            ...
        }

        @Override
        public View getView(final int position)
        {
            View v = getLayoutInflater().inflate(R.layout.tab_holder, null);
            .
            .
            .
            return v;
        }
    }
}

现在片段定义如下:

public class ChatWindowFragment extends Fragment
{
    public String friendId;
    private ListView lv;

    public static ChatWindowFragment newInstance(final String friendId)
    {
        ChatWindowFragment chatWindowFragment = new ChatWindowFragment();
        Bundle bundle = new Bundle();
        bundle.putString("friendId", friendId);
        chatWindowFragment.setArguments(bundle);
        return chatWindowFragment;
    }

    @Override
    public void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.friendId = getArguments().getString("friendId");
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
    {
        View v = inflater.inflate(R.layout.chat_window, container, false);

        this.friendId = getArguments().getString("friendId");
        .
        .
        .
        return v;
    }

    //The rest of the class

}

当我使用FragmentPagerAdapter时,我看不出如何设置每个片段的标签! (显然,我没有使用事务来添加片段!)

编辑2: 我想知道我在做什么,是处理我想要做的正确方法......也欢迎任何其他解决方案!

6 个答案:

答案 0 :(得分:40)

试试这个,

在所有片段中注册广播接收器......就像这样

创建一个扩展所有类中广播接收器的类,例如:

public class FragmentReceiver1 extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
        }    
}

并将此接收器注册到片段的onCreate ...

例如。 getActivity().registerReceiver(new FragmentReceiver1(), new IntentFilter("fragmentupdater"));

现在为每个片段分配一个唯一的ID,如Fragment1为1,Fragment2为2,同样

现在每当你想传递任何数据并更新任何片段时,只需发送一个包含intent in data和“fragmentupdater”作为intent-filter的广播...

例如:

Intent data = new Intent("fragmentupdater");
data.putString("key","data");
data.putInt("fragmentno",1); // Pass the unique id of fragment we talked abt earlier
activity.sendBroadcast(data);

现在你的每个片段都会收到数据,但你可以通过我们在onReceive函数中传递的唯一ID来验证数据是否是同一个片段...,你得到的意图,是我们上面传递的意图

答案 1 :(得分:5)

您是否尝试过FragmentManager.findFragmentByTag()

FragmentManager manager = getSupportedFragmentManager();
//with support package, else
//FragmentManager manager = getFragmentManager()
Fragment fragment = manager.findFragmentByTag("Tag You Created the Fragment");
if (fragment instanceof Fragment1){
    Fragment1 fr = (Fragment1)fragment
    fr.updateData(DATA)
    //or any method of your choice
} 

编辑:我仔细阅读了! instanceOf会将Fragment投射到您的Fragment类中。是你,他建议Fragment1作为简单的名字。此外,您没有提供任何来源来帮助我们。确实,您无法设置Fragment标签,但为什么您认为自己可以获得标签? 通常会通过Fragment添加FragmentManagers,例如

FragmentManager manager = getSupportedFragmnentManager()
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(int containerViewId, Fragment fragment, String tag);
// or transaction.add(Fragment fragment, String tag)
// ...other transactions
transaction.commit()

EDIT2:虽然很容易。根据你的代码你可以打电话

Fragment fragment = mAdapter.getItem(0) // 0||1||2

您应该考虑阅读文档(即约FragmenPagerAdapter)并发布您的源代码,这样我们就不必猜测您需要什么。

答案 2 :(得分:0)

我不知道你在做什么,但听起来你需要使用Observer模式,Callbacks或Listeners。你的片段不能像以下那样:

myservice.addMyEventListener(myFragInstance);

然后您可以“收到特定事件的通知。”

答案 3 :(得分:0)

看看这个答案https://stackoverflow.com/a/16388650

他使用了yourAdapter.notifyDataSetChanged()这是一种预定义的方法。 检查链接以了解其完成情况

编辑: 完成AsyncTask之后,你应该在onPostExecute方法上执行类似的操作:

ResultFragment resultFrag = (ResultFragment) getSupportFragmentManager()
                                 .findFragmentByTag("FragToRefresh");
if (resultFrag != null) {
    resultFrag.refreshData(refreshedArray);
}

在ResultFragment中你需要有refreshData方法,如下所示:

public void refreshData(ArrayList<YourObject> data) {
   yourArray = new ArrayList<YourObject>(data);
   yourAdapter.notifyDataSetChanged();
}

答案 4 :(得分:0)

不得不使用事件总线来简化一切https://github.com/greenrobot/EventBus

答案 5 :(得分:0)

我不确定这是正确的做法
1. 在片段中创建一个公共函数,您将调用它来接收数据。

public void refreshList(List<String> yourData) {
      //referesh your fragment views here
}

2.创建全局片段对象

YourFragment frag = new YourFragment();

3. 将其传递给包含活动中的视图分页器
4.向视图寻呼机添加页面更改侦听器

  viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

            }

            @Override
            public void onPageSelected(int position) {
                switch (position) {
                    case 0:
                        break;

                    case 1:
                        break;
                }
            }

            @Override
            public void onPageScrollStateChanged(int state) {
            }
        });

此处case 0:在选择第一个片段时调用,case 1:在第二个片段被选中时调用..

5.根据其在视图分页器中的位置调用您的函数

case 0: frag.refreshList(yourList);