我正在开发一个项目,我必须在片段之间传递数据。所有数据都是从我的DatabaseHandler class
(SQLiteOpenHelper)提供的。我正在手写这篇文章,所以忽略语法错误,如果有的话。
这是我的Activity
看起来的样子(包含SelectionFragment和InfoFragment):
GridView
)ViewPager
约5-6 child fragments
)
这是我到目前为止所做的事情:
SelectFrag扩展片段:
MyCommunicator communicator;
GridView myGrid;
onItemSelected(... int position, ...) {
communicator.respond("The id i get from getTag()..");
}
public void setCommunicator(MyCommunicator communicator) {
this.communicator = communicator;
}
public interface MyCommunicator {
public void respond(String id);
}
活动扩展FragmentActivity实现SelectFrag.MyCommunicator:
FragmentManager manager;
SelectFrag selectFrag;
InfoFrag infoFrag;
onCreate() {
manager = getSupportFragmentManager();
selectFrag = (SelectFrag) manager.findFragmentById(...);
selectFrag.setCommunicator(this);
}
@Override
public void respond(String id) {
DatabaseHandler db = new DatabaseHandler(this);
try {
CustomObject obj = db.getObj(id);
} finally {
db.close();
}
infoFrag = (InfoFrag) manager.findFragmentById(...);
if(obj != null)
infoFrag.changeObj(id)
setTitle(obj.getName();
}
InfoFrag扩展片段:
ViewPager pager;
Context context;
MyObj obj;
public void changeObj(String id) {
DatabaseHandler db = new DatabaseHandler(context);
this.obj = db.getObj(id);
db.close();
}
protect class MyPagerAdapter extends FragmentPagerAdapter{
public Fragment getItem(int i) {
Fragment frag = null;
switch(i) {
case 0:
frag = new ChildFrag1();
break;
case 1:
frag = new ChildFrag2();
break;
... Goes to case 6 for now.
}
return frag;
}
}
以下是我的布局:
select_frag.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SelectFrag" >
<GridView
android:id="@+id/selectGridView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:columnWidth="56dp"
android:background="#dd5500"
android:horizontalSpacing="5dp"
android:numColumns="auto_fit"
android:paddingLeft="10dp"
android:paddingRight="2dp"
android:paddingTop="3dp"
android:stretchMode="columnWidth"
android:verticalSpacing="5dp" >
</GridView>
</RelativeLayout>
main_activity.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MyActivity"
android:orientation="vertical" >
<fragment
android:id="@+id/selectFragment"
android:name="my.package.SelectFragment"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="3" />
<fragment
android:id="@+id/infoFragment"
android:name="my.package.InfoFragment"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="7" />
</LinearLayout>
info_fragment.xml:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/myPager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.support.v4.view.PagerTitleStrip
android:id="@+id/my_pager_title_strip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:background="#33b5e5"
android:paddingBottom="4dp"
android:paddingTop="4dp"
android:textColor="#fff" />
</android.support.v4.view.ViewPager>
该应用程序当前将信息从selectFrag传递给Activity,后者将其传输到infoFrag。我希望这个ID能够一直到达子片段。我在考虑将InfoCom的MyCommunicator实现并将数据传递给子Fragments,但是不会为不可见的childFragments抛出NullPointerException。
* 注意:* selectFrag和InfoFrag始终在Activity中可见。在selectFrag的GridView中选择新项目时,InfoFrag必须刷新。
感谢您的帮助!
编辑:
我尝试使用“通讯界面”,但我每次都迷路了:(大声笑..有人可以给我一个简短的方法吗?我的所有childrenFragments都可以从selectFrag实现通信器吗?如果是,那是正确的方法吗?我认为InfoFragment应该实现接口并将数据传递给它的'孩子。但是我不知道怎么做并刷新孩子们。我想做的另一件事是将lastItemClicked存储在sharedPreferences中,然后从我的数据库中访问Object。我真的很困惑:/再次感谢!
答案 0 :(得分:6)
我认为你面临着另一个问题。
您需要创建以下组件:
我将概述一个超简化版本。
<强>接口:强> 这很简单:
public interface DataChangeListener {
void onDataChanged();
}
听众列表:这也很容易......在您的控制器/活动/单身人士或您需要执行操作并通知听众的任何地方......
protected List<DataChangeListener> mListeners = new ArrayList<DataChangeListener>();
public void addDataChangeListener(DataChangeListener listener) {
if (listener != null && !mListeners.contains(listener)) {
mListeners.add(listener);
}
}
public void removeDataChangeListener(DataChangeListener listener) {
if (listener != null) {
mListeners.remove(listener);
}
}
然后你的片段......(例如)
public class YourFragment extends Fragment implements DataChangeListener {
private SomeControllerForExample mController;
@Override
public void onPause() {
super.onPause();
mController.removeDataChangeListener(this);
}
@Override
public void onResume() {
super.onResume();
mController.addDataChangeListener(this);
}
}
到目前为止,您在恢复时进行注册,并在不再可见时删除。
您还需要实施该方法......
@Override
public void onDataSetChanged() {
// DO WHATEVER YOU NEED TO DO
}
最后,在你的控制器中有一个通知方法(具有列表的那个)
private void notifyListeners(){
for (DataChangeListener listener : mListeners) {
if (listener != null) {
listener.onDataSetChanged();
}
}
}
这种模式适用于任何事情,这是一种很简单的方法,可以通知您UI已经检索到新数据,必须通知适配器等等。
使用类似的东西重新思考你的问题,事情会容易得多。
答案 1 :(得分:1)
现在找到解决方案。而不是与子片段通信。每次在GridView中选择一个项目时,我都会重新验证ViewPager(在infoFrag中调用changeObj)。 我想我应该早点使用不同的关键字来找到解决方案! :/ Replacing a fragment from ViewPager android