Как узнать, когда заполняется Android ListView

У меня есть дочерняя активность, которая содержит ListView. Эта активность заполняется асинхронно с помощью курсора SQLite. Элементы списка содержат TextView, RadioButton и обычную кнопку. XML показан ниже:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/rlCategoryListItemLayout" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content">
 <TextView android:id="@+id/tvCategoryListItemTitle" style="@style/uwLargeListItemLabelStyle" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:singleLine="true" android:text="This is a test note title" />
 <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="fill_parent" android:layout_alignParentRight="true" android:gravity="center_vertical">
  <RadioButton android:id="@+id/rdoCategoryListItemSelect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_marginRight="10dip" />
  <Button android:id="@+id/btnCategoryListItemDelete" android:background="@drawable/delete_red" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" />
 </LinearLayout>
</RelativeLayout>

Мне нужно сделать некоторую логику, чтобы определить, какой RadioButton выбран по умолчанию, и я не могу сделать это, пока ListView не будет загружен. Проблема в том, что со всеми событиями, которые я пробовал до сих пор (onCreate, onPostCreate, onResume, onWindowFocusChanged), счетчик списка ListView равен нулю. Я также пробовал использовать метод getView в классе ArrayAdapter, но этот метод называется mutliple times, и подсчет дочерних элементов ListView потенциально различается каждый раз, что приводит к неожиданным результатам. По-видимому, эти события увольняются до того, как ListView закончил полностью заполнять свои дочерние элементы.

Есть ли какое-нибудь событие, которое я могу прослушать, или какой-либо другой способ определить, когда ListView закончен, и все его дети доступны для программной модификации?

Спасибо!

Ответы

Ответ 1

Вы можете использовать обработчик для выполнения этой задачи, например:

В вашей деятельности добавьте обработчик как любое другое свойство.

private Handler mListViewDidLoadHanlder = new Handler(new Handler.Callback() { 
    @Override
    public boolean handleMessage(Message message) {
        //Do whatever you need here the listview is loaded
        return false;
    }
});

И внутри метода getView вашего адаптера listview вы сравниваете это, чтобы увидеть, является ли текущая позиция последней, и, таким образом, она закончится (просто поставьте ее перед возвратом):

public View getView(int position, View convertView, ViewGroup parent) {
         //Your views logic here

         if (position == mObjects.size() - 1) {
                mViewDidLoadHanlder.sendEmptyMessage(0);
            }

         return convertView;
     }

Ответ 2

В конце вашей асинхронной работы с базой данных вы можете использовать Handler.post(Runnable) для запуска кода обратно в главном потоке.

Это почти как запуск обратного вызова, который, как вы можете гарантировать, будет запущен после заполнения списка. Вы можете запланировать запуск Runnable в определенное время, если вам нужно все очень тщательно рассчитать.

Я надеюсь, что это было полезно.

Ответ 3

ListView фактически не создает представление для каждого элемента в списке данных, которые он выполняет. Вместо этого он перерабатывает представления, чтобы быть отзывчивыми, а не память. Вы можете переосмыслить то, что вам действительно нужно, когда вы говорите, что ListView нужно заполнить.

Это может помочь, если вы расскажете немного о своем приложении и разместите код.

Ответ 4

Вы можете добавить строковую переменную в свою активность (например, public static String END_LOAD) и установить значение в методе getView (в адаптере), а затем в своей деятельности после

ListView listView = (ListView) findViewById(R.id.recordListView);
        listView.setAdapter(adapter);

Вы можете добавить простой поток, который будет проверять переменную END_LOAD:

Runnable runnable = new Runnable() {
    @Override
    public void run() {
        while (END_LOAD == null || END_LOAD .equals("") ) { // your conditions
        }
        createReadRequest(); // your task to execute
    }
};

new Thread(runnable).start();

Добавьте простое условие, которое может быть вам интересным, тогда, когда условие будет ложным, это потому, что метод getView сделан, теперь вы можете выполнить свой конкретный процесс.