0

ここにある 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) を見つけるのを手伝ってくれる人はいますか? 追加の詳細が必要な場合はお知らせください。ありがとう!

4

1 に答える 1

2

デバイスを回転させると、強制的にonCreate()関数が呼び出され、savedInstanceState!=nullがtrueになる可能性があります。

回転したときに再びonCreate()を実行したくない場合は、次のように実行できます。

まず、次の行をandroidmanifest.xmlに追加します。

android:configChanges="orientation|keyboardHidden"

次に、activity.javaを変更します。

@Override  
public void onConfigurationChanged(Configuration newConfig) {  
  // TODO Auto-generated method stub  
  super.onConfigurationChanged(newConfig);  
  if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {  

  } else if (this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {  

  }  
}  
于 2012-10-19T05:07:40.927 に答える