Почему работает создание нового пользовательского обработчика в пользовательском ArrayAdapter?

1

Я использовал это некоторое время, и я не уверен, нашел ли я эту технику в примере или просто попробовал кучу вещей, пока это, наконец, не сработало. Мой вопрос в том, как эта строка кода,

new ObjectInterfaceHandler(position, o, v);

на самом деле сделать это, где это представление Прослушивает обратные вызовы из ListReadyObject.

package com.scs.stuff;

import java.util.ArrayList;

import android.content.Context;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

public class ListReadyObjectAdapter extends ArrayAdapter<ListReadyObject> {

    public ListReadyObjectAdapter(Context context, int textViewResourceId,
            ArrayList<ListReadyObject> lro) {
        super(context, textViewResourceId, lro);

    }

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

        LinearLayout v;
        v = new LinearLayout(getContext());
        LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
                Context.LAYOUT_INFLATER_SERVICE);
        vi.inflate(R.layout.list_row, v, true);

        ListReadyObject o = getItem(position);

        if (o != null) {

            TextView tt = (TextView) v.findViewById(R.id.toptext);
            TextView bt = (TextView) v.findViewById(R.id.bottomtext);

            if (tt != null) {
                tt.setText(o.getDisplayText());
            }

            if (o.isLiving()) {
                if (bt != null) {
                    // set default text to be shown
                    // until the status thread completes
                    bt.setText("---");
                }
                // start a background thread to update Display State
                o.updateStatus();
                // why does this work
                new ObjectInterfaceHandler(position, o, v);

            } else {
                if (bt != null) {
                    bt.setText("Not Living");
                }
            }
        }
        return v;
    }

    // provides a way for the Object to call back to the list without
    // blocking the UI
    public class ObjectInterfaceHandler implements ListReadyObjectStatusListener {
        int position;
        ListReadyObject o;
        View v;

        private final Handler handler = new Handler();

        public ObjectInterfaceHandler(int position, ListReadyObject o, View v) {
            this.position = position;
            this.o = o;
            this.v = v;
            // register to observe an update from the Object
            o.registerObserver(this);
        }
        @Override
        public void objectInterfaceUpdate() {
            // called from the Object observer pattern
            handler.post(updateBottomText);
        }
        // runnable to put the update on the UI Thread
        private Runnable updateBottomText = new Runnable() {
            @Override
            public void run() {
                TextView bt = (TextView) v.findViewById(R.id.bottomtext);
                if (bt != null) {
                    bt.setText(o.getStatusText());
                }
            }
        };
    }
}

Интерфейс ListReadyObject:

package com.scs.stuff;

public interface ListReadyObject {

    public void registerObserver(ListReadyObjectStatusListener o);

    public void removeObserver(ListReadyObjectStatusListener o);

    public void notifyObservers();

    public String getDisplayText();

    public String getStatusText();

    public boolean isLiving();

    public void updateStatus();

}

Интерфейс ListReadyObjectStatusListener:

package com.scs.stuff;

public interface ListReadyObjectStatusListener {

    public void objectInterfaceUpdate();

}
Теги:
listview
android-arrayadapter

2 ответа

1
Лучший ответ

Он не делает (напрямую) просмотр прослушивания обратных вызовов.

Здесь вы видите, как ListReadyObject передается в конструктор ObjectInterfaceHandler:

ListReadyObject o = getItem(position);
...
new ObjectInterfaceHandler(position, o, v);

В этом конструкторе вы найдете следующее:

o.registerObserver(this);

Таким образом, ObjectInterfaceHandler фактически является тем, кто слушает ListReadyObject. Затем, когда он будет уведомлен об обновлении:

@Override
public void objectInterfaceUpdate() {
    // called from the Object observer pattern
    handler.post(updateBottomText);
}

Он отправляет сообщение своему собственному обработчику для вызова вашего Runnable который обновляет представление:

private Runnable updateBottomText = new Runnable() {
    @Override
    public void run() {
        TextView bt = (TextView) v.findViewById(R.id.bottomtext);
        if (bt != null) {
            bt.setText(o.getStatusText());
        }
    }
};

Это очень распространенный шаблон, называемый шаблоном Observer.

  • 0
    Так как у меня нет ссылки на ObjectInterfaceHandler, где в памяти он живет? Я создаю экземпляр для каждого View в ListView.
  • 0
    Как и любой другой объект, он живет в куче. Он не является сборщиком мусора, потому что реализация ListReadyObject сохраняет ссылку на него, когда регистрирует его в качестве наблюдателя (если он не сломан).
0

Я новичок в Android, и я получаю только половину кода, но единственное, о чем я могу думать, это то, что называется конструктором ObjectInterfaceHandler, который имеет значение для продолжения кода. Поскольку вы создаете экземпляр только (вы не держите ссылки на него), единственным отличием может быть код конструктора:

o.registerObserver(this);

Здесь параметр ListReadyObject ссылается на ObjectInterfaceHandler.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню