2013/03/18

onListItemClick() の中で isChecked() を呼んではいけない?

少し前に、知人に頼まれて作った Androidアプリの動作がおかしいとのこと。
どうも、Galaxy Nexus を 4.0.2 → 4.1.1 にアップデートしてからおかしくなったらしい。

調べてみると、ListActivity.onListItemClick() の中で CheckedTextView.isChecked() を呼んだ時の挙動が変化した模様。

というわけで、以下のようなコードを用意して実験してみました。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MainActivity extends ListActivity {
    private static final String TAG = "MainActivity";
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        String[] listItems = { "1", "2", "3" };
 
        getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
        ListAdapter adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_multiple_choice, listItems);
        setListAdapter(adapter);
    }
 
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // ↓ 少なくとも Android 4.2 までは空関数
        // super.onListItemClick(l, v, position, id);
        CheckedTextView cv = (CheckedTextView) v;
 
        Log.d(TAG, "isChecked " + cv.isChecked());
    }
}

これを、Android 4.0.4 のエミュレータで動作させると以下の通り
// OFF → ON
isChecked false
 
// ON → OFF
isChecked true

Android 4.2 のエミュレータで動作させると以下の通り
// OFF → ON
isChecked true
 
// ON → OFF
isChecked false

完全に動作が逆転しています…

そもそも、以前は「チェックしたのに isChecked が false」という直感に反した仕様だったので、正しい動作をするようになったと言えるのかもしれません。

ただ、この変更がどのような意図で行われたのかが不明です。
Android Developersはチェックしたのですが、それらしい記述を見つけることはできませんでした。
バグフィックスなのか、たまたま挙動が変わってしまったのか…
もし、詳しい方がいらっしゃいましたら、コメントやTwitterで是非教えてください。

とりあえずは、以下のように Android のバージョンをチェックして乗り切ることは可能かもしれません。
1
2
3
4
CheckedTextView cv = (CheckedTextView) v;
 
boolean isChecked = (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.JELLY_BEAN) ?
        !cv.isChecked() : cv.isChecked();

ただし、仕様が明確に提示されていない以上、今後もまた変更が入る可能性はあります。
つまり、onListItemClick() の中では isChecked() を呼ばない方が無難だという事になります。

しかし、チェックされた瞬間に動作させたいことってありますよねぇ…

続き: OnItemClickListener.onItemClick() の中で isChecked() を呼んではいけない?

0 件のコメント: