3

デバイス構成の変更 (言語、向きなどの変更) 後にいくつかのテストを行っていますが、この後、「notifyDataSetChanged()」メソッドが機能していないことに気付きました。

アクション例:

削除、保存などのアクションを実行するたびに updateList() を呼び出しています。ユーザーが削除ボタンをクリックすると、「削除してもよろしいですか?」という DialogFragment が表示され、向きを変更すると、または言語、またはデバイスの構成を選択し、ダイアログで [はい] をクリックすると、データは削除されますが、リストは更新されません。アクティビティを終了してから、戻って変更を確認する必要があります。

ブックアダプター:

public void updateList(ArrayList<Book> books) {
     bookList = books;
     notifyDataSetChanged();
}

構成変更後に機能させるにはどうすればよいですか?

編集:

BookAdapter コンストラクター:

public BookAdapter(Context c, ArrayList<Book> books) {
    context = c;
    bookList = books
    bookDAO = BookDAO.getInstance(context);
}

ブックフラグメント:

public class BookFragment extends Fragment {

    private BookDAO bookDAO;

    private BookAdapter bookAdapter;

    private ListView listBook;

    private View view;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        bookDAO = bookDAO.getInstance(getActivity());

        view = inflater.inflate(R.layout.book_tab, container, false);

        ArrayList<Book> listBook = null;

        try {
            llistBook = bookDAO.getAll();
        } catch (Exception e) {
            Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
            return view;
        }

        bookAdapter = new BookAdapter(getActivity(), listBook);
        listBook = (ListView)view.findViewById(R.id.listBook);
        listBook.setAdapter(bookAdapter);

        return view;

    }

}
4

6 に答える 6

6

シングルトンとして実装して、古い参照からBookAdapter呼び出していないことを確認できます。updateList(..)

必要な変更:

// I am assuming that you are using a BaseAdapter because
// BookAdapter's constructor that you provided in the code above
// does not contain a call to super(....)
public class BookAdapter extends BaseAdapter {

    private static BookAdapter mAdapter;
    private Context context;
    private static ArrayList<Book> bookList;
    private BookDAO bookDAO;

    // To keep at most one instance of BookAdapter
    public static BookAdapter getInstance(Context con, ArrayList<Book> books) {

        // If an instance exists, return it
        if (mAdapter != null) {
            bookList = books;
            return mAdapter;
        }

        // Else, craete a new instance
        mAdapter =  new MyAdapter(con, books);
        return mAdapter;
    }

    // BookAdapter's only constructor is declared as private to restrict access
    private BookAdapter(Context con, ArrayList<Book> books) {
        context = con;
        bookList = books;
        bookDAO = BookDAO.getInstance(context);
    }

    public void updateList(ArrayList<Book> books) {
        bookList = books;
        notifyDataSetChanged();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        // Retrieve object
        Book bookItem = bookList.get(position);

        ....
        ....

}

}

Fragment の onCreateView は次のように変更されます。

bookAdapter = BookAdapter.getInstance(getActivity(), listBook);

ユーザーが [はい] を押したときに実行されるコードAre you sure you want to delete?:

// Remove entry from bookDAO
// Remove entry from listBook
// OR update listBook:
try {
    listBook = bookDAO.getAll();
} catch (Exception e) {
    Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
}

// Assertion: "listBook" does not contain the 
// item that was just deleted from "bookDAO"

// Update ListView's contents
bookAdapter.updateList(listBook);
于 2013-09-18T09:39:02.493 に答える
0

ビューをデータメンバーとして保持しているのはなぜですか?

構成変更全体のビューを維持する場合、構成変更が発生する前の前のインスタンスへの参照を保持します。これはリストを保持するビューであるため、データの更新を見逃す可能性があります。

このフィールドとその使用を削除して、リストが更新されるかどうかを確認してください。

于 2013-09-20T11:30:37.527 に答える
0

アダプターのライフサイクル全体で同じリストを使用してみて、その内容のみを変更します。

public class BookAdapter extends ArrayAdapter<Book> {

    private final booklist;
    // ..

    public BookAdapter(Context c, ArrayList<Book> books) {
        super(c, R.layout.yourlayout, books);
        context = c;
        bookList = books
        bookDAO = BookDAO.getInstance(context);
    }

    public void updateList(ArrayList<Book> books) {
        bookList.clear();
        boolList.addAll(books);
        notifyDataSetChanged();
    }

    // ..
}
于 2013-09-17T03:18:24.743 に答える
-1

問題は、向きなどの構成を変更すると、現在のが再起動されるという事実にあると思いますActivity

このため、コードの一部の部分がまだ存在しない以前のアクティビティを参照していて、動作していないと思いますnotifyDataSetChanged

すぐに試すことができる 2 つのことがあります。

  1. アクティビティのマニフェスト ファイルに次の行を追加します: android:configChanges="orientation|locale". この変更は、システムにとって、オリエンテーションまたは言語の変更中に行う変更を自分で処理することを意味します。したがって、アプリはそれ自体でアクティビティを再作成しなくなります (したがって、アクティビティは同じように機能するはずです)。

  2. もう 1 つのトリックは、関数の先頭に次の行を追加することonCreateViewです setRetainInstance(true);。ドキュメントで説明されているように、この行は構成の変更中にフラグメントの状態を保持します。

アクティビティの再作成 (構成変更など) の間、フラグメント インスタンスを保持するかどうかを制御します。これは、バック スタックにないフラグメントでのみ使用できます。設定されている場合、アクティビティが再作成されると、フラグメントのライフサイクルがわずかに異なります。

  • onDestroy() は呼び出されません (ただし、フラグメントが現在のアクティビティから切り離されているため、onDetach() は呼び出されます)。
  • フラグメントが再作成されていないため、onCreate(Bundle) は呼び出されません。
  • onAttach(Activity) と onActivityCreated(Bundle) は引き続き呼び出されます。

説明したように、Fragmentライフサイクルが少し変わることに注意してください。

3) 最後のオプションは、この回答で詳細に説明されているように、を使用onSaveInstanceStateしてアクティビティの状態を保持することです: https://stackoverflow.com/a/151940/2206688onRestoreInstanceState

于 2013-09-17T13:41:37.757 に答える