Включить/отключить ImageView внутри RecyclerView на основе результата сетевого вызова

У меня есть RecyclerView, который отображает сообщения в твиттере. У каждого элемента списка есть маленькое сердечко, которое вы можете нажать, чтобы поставить «Нравится» сообщению.

Это работает следующим образом: щелчок по значку сердца запускает IntentService, который выполняет вызов API. Затем API возвращает код состояния (например, liked_successfully).

Моя проблема в том, что я хочу отключить этот маленький значок сердца во время выполнения вызова API. Я могу отключить его, когда пользователь нажимает на него, настроив это в Adapter, но включить его снова — это то, что я не знаю, как это сделать.

Мой IntentService может транслировать результат всем зарегистрированным BroadcastReceivers. Я надеялся, что мой адаптер каким-то образом подслушает это и снова активирует значок сердца. Но я не думаю, что вы можете регистрировать такие приемники...

Есть ли способ решить мою проблему?

EDIT: Благодаря помощи ответа ankit aggarwal я смог решить свою проблему. Вот что я сделал (обратите внимание, я выбрал BroadcastReceiver, хотя вы могли бы сделать то же самое с ResultReceiver, как было предложено ankit):

Шаг 1: Передайте adapterPosition вашей службе внутри метода onClick() в вашем адаптере:

public ViewHolder(View view) {
            super(view);
            // Get references to our views          
            heartImageView = (ImageView) view.findViewById(R.id.heartImageView);

            heartImageView.setOnClickListener(new View.OnClickListener(){

                @Override
                public void onClick(View v) {
                    // Get adapter position
                    int adapterPosition = getAdapterPosition();
                    mCursor.moveToPosition(adapterPosition);

                    // Disable your ImageView
                    heartImageView.setClickable(false); 

                    // Start your IntentService, passing in the adapterPosition as an extra
                    //...
            });
       }

Шаг 2: Пусть ваш IntentService вернет (через широковещательную рассылку или иным образом) этот adapterPosition в вашу активность, где вы получите ссылку на эту строку и снова включите функцию ImageView.

public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        Bundle extras = intent.getExtras();
        int adapterPosition = extras.getInt(MyService.ADAPTER_POSITION);

        // Re-enable the clicking of the heartImageView for that specific row in RecyclerView
        RecyclerView.ViewHolder holder =
                mRecyclerView.findViewHolderForAdapterPosition(adapterPosition);
        // Get the view from the ViewHolder
        View view = holder.itemView;
        ImageView heartImageView = (ImageView) view.findViewById(R.id.heartImageView);
        // Re-enable the ImageView
        heartImageView.setClickable(true);
        Log.d("MicroR", "heartImageView enabled again for position: " + String.valueOf(adapterPosition));
    }
}



Ответы (2)


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

EDIT: вы можете использовать это так

public class RandomAdapter extends BaseAdapter{
    public void updateAdapter(String <Some value>){
        // Do whatever you want here
    }
}

при создании адаптера сделайте объект переменной уровня класса, поэтому onReceive() из resultReceiver вы можете называть его как

mAdapter.updateAdapter(<some value>);

Если вы хотите отредактировать свою строку, вам нужно получить позицию элемента строки.

ListView list = getListView();
int firstVisibleElement = postListView.getFirstVisiblePosition();
int lastVisibleElement = postListView.getLastVisiblePosition();
if (position >= firstVisibleElement && position <= lastVisibleElement) {
    View view = postListView.getChildAt(position - firstVisibleElement);
    // now get your like imageview from view and do whatever you want to do with it
}
person Ankit Aggarwal    schedule 21.02.2016
comment
Может быть, тогда мне следует спросить вас, как вы создаете метод в своем классе адаптера, который может вызываться Activity/Fragment, получающим результаты через ResultReceiver? - person Micro; 21.02.2016
comment
Спасибо за обновление. Но это приводит меня к другому вопросу: как я могу включить/отключить ImageView в этой конкретной строке в mAdapter.updateAdapter(<some value>)? Я мог бы передать идентификатор курсора updateAdapter(), но после этого..? - person Micro; 21.02.2016
comment
Не передавайте идентификатор курсора. просто передайте позицию элемента. Проверьте обновленное решение - person Ankit Aggarwal; 21.02.2016
comment
Ну, я использую RecyclerView.. Так что я могу передать позицию элемента обратно в адаптер. Но однажды внутри адаптера я не уверен, что делать с этой позицией элемента - вот как я могу получить ImageView на основе этой позиции элемента внутри адаптера...? - person Micro; 21.02.2016
comment
Я бы посоветовал вам не выполнять эту часть обновления представления внутри адаптера, просто делайте это внутри своей деятельности. Вы можете изменить его с помощью View view = postListView.getChildAt(position - firstVisibleElement); ImageView img = view.findViewById (R.id.your_drawable_id); img.setImageResource(‹ваш рисунок›); Здесь переменная position обозначает положение редактируемого элемента списка. - person Ankit Aggarwal; 21.02.2016
comment
А, очень умно. Я обновил свой вопрос, чтобы отразить реализацию, которая сработала для меня. Ваш ответ был бесценен!! - person Micro; 21.02.2016

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

person Farhad Faghihi    schedule 21.02.2016