【发布时间】:2015-04-26 09:55:07
【问题描述】:
我对 android、java 等几乎是新人,对 Fragment 也是新人。 我有一个活动(A),它使用片段(B)显示一个列表。选择此列表中的一个项目,相同的片段将更改为使用片段 (C) 显示另一个列表。 它可以工作,除非我在显示第二个列表 (C) 时旋转设备。 此外,当它显示第一个列表 (B) 时,如果我旋转设备,它会完美运行。
错误日志:
04-26 11:30:32.769: E/AndroidRuntime(2882): FATAL EXCEPTION: main
04-26 11:30:32.769: E/AndroidRuntime(2882): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.traffic/com.example.traffic.ListTriplines}: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.traffic.ListPoints: make sure class name exists, is public, and has an empty constructor that is public
(...)
04-26 11:30:32.769: E/AndroidRuntime(2882): Caused by: android.support.v4.app.Fragment$InstantiationException: Unable to instantiate fragment com.example.traffic.ListPoints: make sure class name exists, is public, and has an empty constructor that is public
(...)
04-26 11:30:32.769: E/AndroidRuntime(2882): Caused by: java.lang.InstantiationException: com.example.traffic.ListPoints
活动 A(java + XML):
public class MainA extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_triplines);
}
@Override
public void onTripSelected(int cod) {
Fragment pointsFragment = new ListPoints(cod);
FragmentTransaction fTransaction = fManager.beginTransaction();
fTransaction.replace(R.id.trips_points_fragment, pointsFragment);
fTransaction.addToBackStack(null);
fTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fTransaction.commit();
}
@Override
public void onPointSelected(int pos) {
//do some stuff (using pos)
(...)
}
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/main_title"
style="@style/HelpTitle"
android:text="@string/listtrips_title"
/>
<fragment
android:id="@+id/trips_points_fragment"
android:name="com.example.traffic.FragmentB"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</RelativeLayout>
片段 B(java + XML):
(...)
import android.support.v4.app.Fragment;
(...)
public class FragmentB extends Fragment {
private OnTripSelectedListener tSelected;
private static ListTriplines listtriplines;
private Context context;
private LayoutInflater inflater;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
//CHECK che nell'ACTIVITY sia IMPLEMENT il listener
try {
tSelected = (OnTripSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnTripSelectedListener");
}
listtrips = (ListTriplines) activity;
context = activity.getApplicationContext();
inflater = LayoutInflater.from(activity);
}
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup vG, Bundle savedInstanceState) {
//Inflate the layout for this fragment
final View viewResult = inflater.inflate(R.layout.list_trips, vG, false);
listview_trips = (ListView) viewResult.findViewById(R.id.trips_listview);
return viewResult;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
listAdapter = new CursorAdapter(...);
listview_trips.setAdapter(listAdapter);
listview_trips.setOnItemClickListener(onItemClickListener);
listview_trips.setOnItemLongClickListener(onItemLongClickListener);
}
public interface OnTripSelectedListener {
public void onTripSelected(int cod);
}
private OnItemClickListener onItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> av, View v, int pos, long id) {
tSelected.onTripSelected(id);
}
};
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ExpandableListView
android:id="@+id/trips_explistview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/gray"
/>
</LinearLayout>
片段 C(java + XML):
(...)
import android.support.v4.app.Fragment;
(...)
public FragmentC extends Fragment {
private OnPointSelectedListener pListener;
private static ListTriplines listtrips;
private Context context;
private int cod;
public ListPoints (int _cod) {
this.cod = _cod;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
pListener = (OnPointSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnPointSelectedListener");
}
listtrips = (ListTriplines) activity;
context = activity.getApplicationContext();
inflater = LayoutInflater.from(activity);
}
@Override
public View onCreateView (LayoutInflater inflater, ViewGroup vG, Bundle savedInstanceState) {
//Inflate the layout for this fragment
final View viewResult = inflater.inflate(R.layout.list_points, vG/*null*/, false);
listview_points = (ListView) viewResult.findViewById(R.id.points_listview);
return viewResult;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
pointsAdapter = new CursorAdapter(...);
listview_points.setAdapter(pointsAdapter);
listview_points.setOnItemClickListener(onItemClickListener);
}
public interface OnPointSelectedListener {
public void onPointSelected(int pos);
}
private OnItemClickListener onItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> av, View v, int pos, long id) {
pListener.onPointSelected(pos);
}
};
}
<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/points_listview"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@color/gray"
/>
</LinearLayout>
也许我的问题是因为我使用 1 个片段来显示 2 个不同的片段?在这种情况下,我使用 2 个片段来解决它并替换那个必须显示的片段(使用 VISIBILITY.GONE)?
谢谢
EDIT:在 XML 主要活动 (A) 中,我更改了片段名称 -> FragmentB(我发布问题时忘记更改它)。
N.B:我需要对此进行下划线 -> 当活动 (A) 开始时,它会加载 FragmentB (B);然后我选择一个项目并加载 FragmentC (C);当我在 XML 中旋转时,有 FragmentB(显然),而活动(A)必须加载 FragmentC(C)。我不知道Android是否可以处理这种情况。
解决方法:
1) Ortsinton 修改后的 LogCat(创建一个空的构造函数,并使用“BUNDLE”传递一些参数):
04-26 14:24:46.809: E/AndroidRuntime(11558): FATAL EXCEPTION: main
04-26 14:24:46.809: E/AndroidRuntime(11558): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.traffic/com.example.traffic.ListTriplines}: android.view.InflateException: Binary XML file line #23: Error inflating class fragment
04-26 14:24:46.809: E/AndroidRuntime(11558): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1659)
(...)
04-26 14:24:46.809: E/AndroidRuntime(11558): Caused by: android.view.InflateException: Binary XML file line #23: Error inflating class fragment
(...)
04-26 14:24:46.809: E/AndroidRuntime(11558): Caused by: java.lang.IllegalStateException: Fragment com.example.traffic.ListTrips did not create a view.
2) 以编程方式(不是从 XML)实例化片段: - 在 XML 中,您必须使用“布局”(我使用 FrameLayout)而不是“片段”; - 在java脚本中,你必须使用“FragmentTransaction”;
3) Android 会处理 Activity(包含 Fragment),Android 会像开始时一样重新创建它,因此您必须实现 onSaveInstanceState(保存数据)和 onRestoreInstanceState(修改 Activity)就像您旋转设备时一样)。
【问题讨论】:
标签: java android android-fragments android-activity fragment