【发布时间】:2014-09-22 06:36:15
【问题描述】:
我有一个非常简单的应用程序,可以在横向模式和纵向模式之间切换。在纵向模式下,我有一个在列表中显示数据的片段,在横向模式下,我有另一个在网格中显示我的数据的片段。只是为了重新迭代有两个不同的片段,一个以纵向模式呈现数据的 ListFragment 和一个以横向模式显示数据的“GridFragment”。只要设备方向不变,各个片段就会正确呈现。然而,当设备从纵向翻转到横向或反之亦然时,该应用程序就会崩溃。
首先是我的错误日志。设备从纵向模式翻转到横向模式时的错误日志:
09-22 11:48:38.990:E/AndroidRuntime(29737):致命异常:主要 09-22 11:48:38.990: E/AndroidRuntime(29737): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.funapp.ssnd/com.funapp.ssnd.MainActivity}: java.lang.RuntimeException: 你的content 必须有一个 id 属性为 'android.R.id.list' 的 ListView 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3677) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.access$700(ActivityThread.java:149) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.os.Handler.dispatchMessage(Handler.java:99) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.os.Looper.loop(Looper.java:153) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.main(ActivityThread.java:4987) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 java.lang.reflect.Method.invokeNative(Native Method) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 java.lang.reflect.Method.invoke(Method.java:511) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584) 09-22 11:48:38.990: E/AndroidRuntime(29737): at dalvik.system.NativeStart.main(Native Method) 09-22 11:48:38.990: E/AndroidRuntime(29737): Caused by: java.lang.RuntimeException: 你的内容必须有一个 id 属性为 'android.R.id.list' 的 ListView 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.ListFragment.ensureList(ListFragment.java:344) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.ListFragment.onViewCreated(ListFragment.java:145) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:956) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1901) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:567) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.Activity.performStart(Activity.java:5030) 09-22 11:48:38.990: E/AndroidRuntime(29737): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157) 09-22 11:48:38.990: E/AndroidRuntime(29737): ... 12 更多
以及设备从横向变为纵向时的错误日志:
09-22 11:52:20.906: E/AndroidRuntime(29943): 致命异常: main 09-22 11:52:20.906: E/AndroidRuntime(29943): java.lang.RuntimeException: 无法启动活动 ComponentInfo{com.funapp.ssnd/com.funapp.ssnd.MainActivity}: java.lang.NullPointerException 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2211) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3677) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.access$700(ActivityThread.java:149) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread$H.handleMessage(ActivityThread.java:1306) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.os.Handler.dispatchMessage(Handler.java:99) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.os.Looper.loop(Looper.java:153) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.main(ActivityThread.java:4987) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 java.lang.reflect.Method.invokeNative(Native Method) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 java.lang.reflect.Method.invoke(Method.java:511) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:821) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 com.android.internal.os.ZygoteInit.main(ZygoteInit.java:584) 09-22 11:52:20.906: E/AndroidRuntime(29943): at dalvik.system.NativeStart.main(Native Method) 09-22 11:52:20.906: E/AndroidRuntime(29943): 引起: java.lang.NullPointerException 09-22 11:52:20.906: E/AndroidRuntime(29943): at com.funapp.ssnd.DetailsFragment.onActivityCreated(DetailsFragment.java:59) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.Fragment.performActivityCreated(Fragment.java:1512) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:962) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1121) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1103) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:1901) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:567) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1166) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.Activity.performStart(Activity.java:5030) 09-22 11:52:20.906: E/AndroidRuntime(29943): 在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2157) 09-22 11:52:20.906: E/AndroidRuntime(29943): ... 12 更多
包含 Fragments 的 Activity:
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Configuration config = getResources().getConfiguration();
if(config.orientation == Configuration.ORIENTATION_PORTRAIT){
setContentView(R.layout.activity_main);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
MemberListFragment fragment1 = new MemberListFragment();
transaction.add(R.id.fragment_container,fragment1);
transaction.commit();
}
if(config.orientation == Configuration.ORIENTATION_LANDSCAPE){
setContentView(R.layout.activity_main);
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
DetailsFragment fragment2 = new DetailsFragment();
transaction.add(R.id.fragment_container,fragment2);
transaction.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
还有布局文件。对于纵向模式:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView android:id="@id/android:list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:drawSelectorOnTop="false"/>
</LinearLayout>
对于横向模式:
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="90dp"
android:numColumns="3"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
还有碎片。对于纵向模式:
import java.util.ArrayList;
import java.util.List;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MemberListFragment extends ListFragment {
String[] membersList;
Integer[] imageList;
ListView listView;
List<RowItem> rowItems;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle){
return inflater.inflate(R.layout.fragment_layout, container,false);
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
rowItems = new ArrayList<RowItem>();
membersList = (getResources().getStringArray(R.array.snsd_members));
imageList = new Integer[membersList.length];
for(int i=0; i<membersList.length; i++){
imageList[i] = R.drawable.home;
}
for(int i=0; i<membersList.length; i++){
RowItem item = new RowItem(imageList[i], membersList[i]);
rowItems.add(item);
}
listView = (ListView) getListView();
SNSDAdapter adapter = new SNSDAdapter(getActivity().getApplicationContext(),
R.layout.list_element, rowItems);
listView.setAdapter(adapter);
}
}
和横向模式:
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.GridView;
public class DetailsFragment extends Fragment {
String[] membersList;
Integer[] imageList;
GridView gridView;
List<RowItem> rowItems;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle){
View view = inflater.inflate(R.layout.fragment_layout, container,false);
gridView = (GridView)view.findViewById(R.id.grid_view);
return view;
}
@Override
public void onActivityCreated(Bundle savedInstanceState){
super.onActivityCreated(savedInstanceState);
rowItems = new ArrayList<RowItem>();
membersList = (getResources().getStringArray(R.array.snsd_members));
imageList = new Integer[membersList.length];
for(int i=0; i<membersList.length; i++){
imageList[i] = R.drawable.home;
}
for(int i=0; i<membersList.length; i++){
RowItem item = new RowItem(imageList[i], membersList[i]);
rowItems.add(item);
}
Log.v("ROW ITEMS",rowItems.toString());
GridAdapter adapter = new GridAdapter(getActivity().getApplicationContext(),rowItems);
gridView.setAdapter(adapter);
}
}
我花了很多时间试图解决这个问题,但没有找到解决方案。这可能是因为当屏幕旋转时我的 Fragments 并没有真正“销毁”,从而阻止了新的 Fragment 取代它的位置?任何解决方案或某些方向将不胜感激。
【问题讨论】:
-
异常来自您的片段代码。您能否也显示此代码(相关部分)?
-
@Szymon 我也添加了片段代码。
-
您的清单中的活动声明中是否有类似“android:configChanges="orientation"" 的行?
-
@labreu 不,我的清单中没有该设置。
-
如果知道是否有帮助,如果我在横向模式下使用列表视图并将一个片段替换为另一个片段,则方向更改是无缝的并且应用程序不会崩溃。然而,在这种情况下,从列表视图切换到网格视图(反之亦然)不会给我预期的结果。同样在 MainActivity 中,我不替换任何片段,而是在每次设备方向更改时添加它们。这是解决这个问题的正确方法吗?
标签: android android-fragments android-orientation