ここにある FragmentsBasic.zip サンプル プロジェクトに基づくアプリの作成を開始しました: http://developer.android.com/training/basics/fragments/index.html
独自のコードを開始する前に、ActionBarSherlock をインポートして、すべてが期待どおりに機能するようにしました。
状況: 1 つのメイン アクティビティ クラス (TaskListActivity) と 3 つのフラグメント クラスがあります。電話でアプリケーションを実行する場合、TaskListActivity は最初に TaskListFragment をロードし、ユーザーがアクション バーの「新しいタスク」アイコンに触れると、TaskListFragment を NewTaskFragment に置き換えます。このフラグメントには、EditText と Button ビューを含むレイアウトがあります。ユーザーがテキストを入力して「完了」ボタンを押すと、テストが ListView に追加されます。
問題: デバイスのローテーションが発生しない限り、すべてが期待どおりに機能します。リストにアイテムを追加する前または後にデバイスを回転させても、次のエラーが発生します。
10-18 23:19:40.838: E/TaskListActivity(2021): Fragment has a null value
10-18 23:19:40.848: E/AndroidRuntime(2021): FATAL EXCEPTION: main
10-18 23:19:40.848: E/AndroidRuntime(2021): java.lang.NullPointerException
10-18 23:19:40.848: E/AndroidRuntime(2021): at com.sample.testapp.TasksListActivity.onNewTaskAdded(TasksListActivity.java:169)
10-18 23:19:40.848: E/AndroidRuntime(2021): at com.sample.testapp.NewTaskFragment$2.onClick(NewTaskFragment.java:63)
10-18 23:19:40.848: E/AndroidRuntime(2021): at android.view.View.performClick(View.java:2449)
10-18 23:19:40.848: E/AndroidRuntime(2021): at android.view.View$PerformClick.run(View.java:9027)
私のアクティビティは次のようになります。
public class TasksListActivity extends SherlockFragmentActivity
implements TasksListFragment.OnTaskSelectedListener, NewTaskFragment.OnNewTaskAddedListener {
private ArrayList<Task> tasks;
private String taskName;
private TasksListFragment firstFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tasks_list);
if (findViewById(R.id.fragment_container) != null) {
if (savedInstanceState != null) {
return;
}
firstFragment = new TasksListFragment();
// In case this activity was started with special instructions from an Intent,
// pass the Intent's extras to the fragment as arguments
firstFragment.setArguments(getIntent().getExtras());
// Add the fragment to the 'fragment_container' FrameLayout
getSupportFragmentManager().beginTransaction()
.add(R.id.fragment_container, firstFragment).commit();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_new:
//Toast.makeText(this, "Tapped new task", Toast.LENGTH_SHORT).show();
// try code from Fragment sample
NewTaskFragment newTaskFragment = (NewTaskFragment)getSupportFragmentManager().findFragmentById(R.id.task_fragment);
if(newTaskFragment != null){
// if itemFragment is available we are in two-pane layout
// Call method in NewItemFragment to update its content
//itemFragment.
}
else{
// if the frag is not available, we are in one-pane layout and must swap fragments
// Create fragment and give it an argument for the selected article
newTaskFragment = new NewTaskFragment();
Bundle args = new Bundle();
//args.putInt(NewItemFragment.ARG_POSITION, position);
newTaskFragment.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view wiht this fragment,
// and add the transaction to the back stack so the user can navigate back
transaction.replace(R.id.fragment_container, newTaskFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
break;
}
return super.onOptionsItemSelected(item);
}
}
public void onNewTaskAdded(String newItem){
this.taskName = newItem;
if(firstFragment == null){
Log.e("TaskListActivity", "Fragment has a null value");
}
firstFragment.onItemAdded(this.taskName); // This is line 169
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, firstFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
}
NewItemFragment には次のものがあります (インターフェイスは示されていません)。
public class NewTaskFragment extends SherlockFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.new_task_fragment, container, false);
int layout = R.layout.new_task_fragment;
Log.v("NewTaskFragment", "The layout to use is (NewTask): " + layout);
final EditText myEditText = (EditText)view.findViewById(R.id.newTask);
final Button doneButton = (Button)view.findViewById(R.id.addNewTask);
final InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
String newItem = myEditText.getText().toString();
onNewTaskAddedListener.onNewTaskAdded(newItem); // This is line 63
myEditText.setText("");
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
});
return view;
}
NullPointerException によってフラグが立てられている 169 行目 (アクティビティ) と 63 行目 (フラグメント) をコメントで強調表示しました。onNewTaskAdded にコードを追加したところ、ローテーション後にフラグメントの値が null であることを確認できました。回転後にオブジェクトが null に変わる理由 (したがって NullPointerException) を見つけるのを手伝ってくれる人はいますか? 追加の詳細が必要な場合はお知らせください。ありがとう!