我已经为此挣扎了一段时间了。我有一个相当复杂的系统,包括一个库模块和应用程序模块。
库模块包含活动:AbstractActivity <- AbstractListActivityFragments: AbstractFragment <- (AbstractListFragment &AbstractEditFragment)
app模块包含活动:WineListActivity (-> AbstractListActivity)Fragments: WineListFragment &EditWineFragment (-> AbstractList &AbstractEdit碎片)
在启动时,WineListActivity被加载并与WineListFragment一起显示。当从列表中选择葡萄酒时,片段将替换为EditFragment。当用户按下后退或保存按钮时,应用程序应该执行onbackpressed活动并再次显示WineListFragment。这里是崩溃发生的地方。对此有任何帮助将不胜感激。我研究这个已经有一段时间了。错误:
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: FATAL EXCEPTION: main
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: Process: com.toteki.winetaster, PID: 4148
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: java.lang.IllegalArgumentException: No view found for id 0x7f0c004f (com.toteki.winetaster:id/content_container) for fragment WineListFragment{423e51d0 #0 id=0x7f0c004f}
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1018)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1207)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:958)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1625)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:561)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v4.app.FragmentActivity.onBackPressed(FragmentActivity.java:166)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.app.Activity.onKeyUp(Activity.java:2193)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.KeyEvent.dispatch(KeyEvent.java:2664)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.app.Activity.dispatchKeyEvent(Activity.java:2423)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v7.internal.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:50)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:224)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2017)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$ViewPostImeInputStage.processKeyEvent(ViewRootImpl.java:3848)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3822)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3395)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3445)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3414)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3521)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3422)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3578)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3395)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3445)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3414)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3422)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3395)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3445)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3414)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3554)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3714)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2021)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1715)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1706)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:1998)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.os.MessageQueue.nativePollOnce(Native Method)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.os.MessageQueue.next(MessageQueue.java:138)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.os.Looper.loop(Looper.java:123)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5146)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at java.lang.reflect.Method.invokeNative(Native Method)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:515)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:732)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:566)
09-12 20:50:50.625 4148-4148/com.toteki.winetaster E/AndroidRuntime: at dalvik.system.NativeStart.main(Native Method)
类:AbstractActivity
public abstract class AbstractActivity extends AppCompatActivity {
public final static String TAG = "AbstractActivity";
protected AbstractFragment fragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_abstract);
}
public void addFragment(AbstractFragment fragment) {
Log.d(TAG, "addFragment");
this.fragment = fragment;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.addToBackStack(this.fragment.TAG);
transaction.add(com.toteki.library.R.id.content_container, this.fragment, this.fragment.TAG).commit();
}
public void replaceFragment(AbstractFragment fragment, boolean addToBackStack) {
Log.d(TAG, "replaceFragment");
this.fragment = fragment;
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if(addToBackStack) {
transaction.addToBackStack(this.fragment.TAG);
}
transaction.replace(com.toteki.library.R.id.content_container, this.fragment, this.fragment.TAG).commit();
}
public abstract void onTaskSuccessful(String tag);
public abstract void onTaskFailure(String tag);
}
WineListActivity
public class WineListActivity extends AbstractListActivity {
public final static String TAG = "WineListActivity";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
WineDataSource.instance().open(this);
WineDataSource.instance().delete();
WineDataSource.instance().close(this);
addFragment(new WineListFragment());
}
@Override
public void onListItemClicked(Rateable r) {
Bundle bundle = new Bundle();
bundle.putSerializable("currentWine", r);
AbstractFragment fragment = new EditWineFragment();
fragment.setArguments(bundle);
replaceFragment(fragment, true);
}
}
WineListFragment
public class WineListFragment extends AbstractListFragment {
public final static String TAG = "WineListFragment";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
for(int i = 0; i < 5; i++) {
Wine w = new Wine();
w.setName("Test " + i);
WineController.instance().create(w);
}
adapter = new WineListAdapter(activity, WineController.instance().getList());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
list.setAdapter(adapter);
return v;
}
}
WineListAdapter
public class WineListAdapter extends RecyclerView.Adapter {
private AbstractActivity activity;
private List<Wine> wineList;
public WineListAdapter(AbstractActivity activity, List<Wine> wineList) {
this.activity = activity;
this.wineList = wineList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_wine_list, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Wine wine = wineList.get(position);
((ViewHolder) holder).getBinding().setVariable(BR.wine, wine);
((ViewHolder) holder).getBinding().executePendingBindings();
}
@Override
public int getItemCount() {
return wineList.size();
}
private class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private ItemWineListBinding binding;
public ViewHolder(View v) {
super(v);
v.setOnClickListener(this);
binding = DataBindingUtil.bind(v);
}
public ViewDataBinding getBinding() {
return binding;
}
@Override
public void onClick(View view) {
((AbstractListActivity) activity).onListItemClicked(binding.getWine());
}
}
}
EditWineFragment
public class EditWineFragment extends AbstractEditFragment {
public final static String TAG = "EditWineFragment";
private FragmentEditWineBinding currentWineBinding;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
Bundle bundle = this.getArguments();
if (bundle != null) {
currentRateable = (Wine) bundle.getSerializable("currentWine");
}
if(currentRateable == null) {
currentRateable = new Wine();
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_edit_wine, container, false);
currentWineBinding = DataBindingUtil.setContentView(activity, R.layout.fragment_edit_wine);
currentWineBinding.setWine((Wine) currentRateable);
return v;
}
protected void actionSave() {
activity.onBackPressed();
currentRateable = currentWineBinding.getWine();
new CreateTask(activity, WineDataSource.instance(), WineController.instance()).execute(currentRateable);
}
}
acitivty_abstract.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/content_container"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f9d107">
</LinearLayout>
</LinearLayout>
fragment_edit_wine.xml
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto" >
<data>
<variable name="wine" type="com.toteki.winetaster.model.Wine"/>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="@dimen/margin_medium"
android:background="#e90f0f">
<com.toteki.library.view.CustomEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true"
custom:input="@{wine.name}"
custom:header="@string/header_name"
custom:hint="@string/hint_name"
android:background="#09ef06" />
</RelativeLayout>
</layout>
编辑:我删除了EditWineFragment的onCreateView,按下后退按钮时一切都很好(除了实际的布局没有显示)。所以我猜我创建/添加EditWineFragment视图布局的方式是问题所在。
问题出在数据绑定上。根据setContentView
的文档,将活动的布局替换为:
将Activity的内容视图设置为给定的布局,并返回关联的绑定。
因此,当您结束片段和FragmentManager试图恢复WineListFragment
时,content_container
已经消失了。因此,前面的片段不能放在布局中,并抛出异常。