ViewPager Activity 通知特定事件的 Fragment

Posted

技术标签:

【中文标题】ViewPager Activity 通知特定事件的 Fragment【英文标题】:ViewPager Activity to notify a Fragment of a specific event 【发布时间】:2012-02-15 22:15:03 【问题描述】:

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

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

为了更简单: 我的 ViewPager 活动:[Fragment 0] [Fragment 1] [Fragment 2]

后台服务告诉我(通过广播)更新Fragment 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: 我想知道我在做什么,是否是处理我想做的事情的正确方法......也欢迎任何其他解决方案!

【问题讨论】:

你尝试过我的建议了吗.... 【参考方案1】:

试试这个,

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

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

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

并在片段的 onCreate 中注册此接收器 ...

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

现在为每个片段分配一个唯一的 id,例如 1 用于 Fragment1,2 用于 Fragment2 等等

现在,当您想要传递任何数据并更新任何片段时,只需发送一个广播,其中包含意图中的数据和“fragmentupdater”作为意图过滤器......

例如:

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 来验证同一片段的数据是否...,您得到的意图是我们在上面传递的意图

【讨论】:

如果您不使用多个进程,请考虑使用developer.android.com/reference/android/support/v4/content/… 而不是全局广播。当然,您总是可以只实现自己的观察者模式,让片段注册到服务中,以便在它感兴趣的更改发生时被告知。 @King RV 我已授予您赏金并建议对您的帖子进行编辑!谢谢......你的建议可以完成工作,我想知道这个问题是否有更好/更简单的解决方案!再次感谢 这是一个非常复杂的解决方案(尽管它有效)。有没有更简单的解决方案来重新加载 viewpager 的内容?比如移除所有子视图并重新加载。 作为说明,我必须在片段的 onAttach 方法中注册接收器。如果我在 onCreate 中注册它就不会触发。不知道为什么... 用什么方法注销?【参考方案2】:

你试过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)并发布您的源代码,这样我们就不必猜测您需要什么。

【讨论】:

您仔细阅读我的问题了吗?我说,所有片段都是从同一个类中实例化的!所以很明显我不能使用“instanceof”。此外,据我所知,片段上没有可用的“setTag()”方法。所以我可能无法使用标签初始化片段!非常感谢任何帮助! 看编辑部分!我仍然不知道该怎么做,所以非常感谢任何建议!【参考方案3】:

我遇到了同样的问题,但使用 localBroadcastReceiver 解决了这个问题,如下所示:

在你的活动中创建一个接收器并注册它:

 /**
 * ******************************
 * Receiver to process the message
 * *******************************
 */
private BroadcastReceiver onNotice = new BroadcastReceiver() 
    @Override
    public void onReceive(Context context, Intent intent) 
        //You can send any extra data if you need like this
        final int type = intent.getIntExtra("fragment.data", -1);
        Log.d(tag, "main class: " + type);
        //also refresh your fragment like this
        mViewPager.getViewPager().getAdapter().notifyDataSetChanged();
    
;    

@Override
protected void onResume() 
    super.onResume();

    //Register a localbroadCast with the your filter
    IntentFilter thinaireFilter = new IntentFilter("your.filter");
    LocalBroadcastManager.getInstance(this).registerReceiver(onNotice, thinaireFilter);

记得删除 LocalBroadCast

//remove the LocalBroadCast when no need it
@Override
protected void onPause() 
    super.onPause();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);

@Override
protected void onDestroy() 
    super.onDestroy();
    LocalBroadcastManager.getInstance(this).unregisterReceiver(onNotice);

从任何您想要的适配器、服务等发送您的广播。

Intent sendBroadCastData = new Intent("your.filter");
sendBroadCastData.putExtra("fragment.data", myData);
LocalBroadcastManager.getInstance(context).sendBroadcast(sendBroadCastData);

希望对他人有所帮助。

【讨论】:

【参考方案4】:

我不太了解您在做什么,但听起来您需要使用观察者模式、回调或侦听器。你的片段不能做类似的事情:

myservice.addMyEventListener(myFragInstance);

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

【讨论】:

【参考方案5】:

看看这个答案https://***.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();

【讨论】:

始终建议编写可能“自包含”的答案 - 包含问题的解决方案,而不仅仅是链接到另一个答案。也许是包含最相关的 sn-p 的编辑? :)【参考方案6】:

不得不使用事件总线让一切变得简单https://github.com/greenrobot/EventBus

【讨论】:

【参考方案7】:

我不确定这是不是正确的做法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);

【讨论】:

以上是关于ViewPager Activity 通知特定事件的 Fragment的主要内容,如果未能解决你的问题,请参考以下文章

友盟-推送-Andorid-消息推送-打开通知消息进入特定Activity操作?

让 viewpager2 响应标签点击事件

android 对话框Dialog拦截activity事件通知

android 对话框Dialog拦截activity事件通知

android 对话框Dialog拦截activity事件通知

android 对话框Dialog拦截activity事件通知