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
来显示不同的信息。 (显然ListView
被ArrayAdapter
填充。)
后台服务也在运行,并不断从 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操作?
android 对话框Dialog拦截activity事件通知
android 对话框Dialog拦截activity事件通知