Фрагмент не будет обновляться после открытия уведомления

#java #android #android-fragments #android-notifications

#java #Android #android-фрагменты #android-уведомления

Вопрос:

Я создаю приложение для чата, и у меня возник вопрос о моем фрагменте, содержащем listview со всеми чатами.

Когда пользователь получает сообщение, список чатов обновляется (отображается последнее сообщение для каждого чата) (изображение 1).

Когда чат не отображается, а в этом чате получено сообщение, пользователь получит уведомление (изображение 2)

На этом этапе начинается проблема. Когда пользователь нажимает на уведомление, просмотр списка чатов, похоже, не работает. Когда пользователь получает другое сообщение после нажатия на уведомление, его / ее телефон будет вибрировать, но просмотр списка чатов не изменится.

Другие представления работают после нажатия на уведомление.

Ниже приведен фрагмент кода, который обрабатывает обновление listview.

     protected PacketListener packetListener = new PacketListener() {

    @Override
    public void processPacket(Packet packet) {
        final Message message = (Message) packet;

        if (message.getBody() != null) {
            final String fromName = StringUtils.parseName(message.getFrom());

            runOnUiThread(new Runnable(){

                @Override
                public void run() {

                    Boolean seen = false;
                    if(ChatFragment.currentChat != null amp;amp; ChatFragment.currentChat.getContact().getUsername().equals(fromName) amp;amp; VisibilityHelper.appIsVisible() amp;amp; VisibilityHelper.fragmentIsVisible(ChatFragment.fragmentClassName)) {
                        seen = true;
                    }

                    Long chat_id = chatsDataSource.getChatByContactId(contactsDataSource.getContactByUsername(fromName).getId()).getId();
                    ChatMessage newChatMessage = chatMessagesDataSource.insertChatMessage(chat_id, ConstantHelper.CHAT_MESSAGES_TYPE_RECEIVED, seen, DateHelper.getDatetime(), message.getBody());

                    Log.d("DEBUG", VisibilityHelper.sCurrentFragmentClassName);
                    if(VisibilityHelper.appIsVisible() amp;amp; VisibilityHelper.fragmentIsVisible(ChatsFragment.fragmentClassName)) {
                        ChatsFragment chatsFragment = (ChatsFragment) getFragmentManager().findFragmentByTag(ChatsFragment.fragmentClassName);
                        Log.d("DEBUG", "REFRESHING");
                        chatsFragment.refreshChatsList();
                    }

                    if(!VisibilityHelper.appIsVisible()) {
                        notificationHelper.externalNotification(getBaseContext(), newChatMessage);
                    } else {
                        if(ChatFragment.currentChat != null amp;amp; ChatFragment.currentChat.getContact().getUsername().equals(fromName) amp;amp; VisibilityHelper.appIsVisible() amp;amp; VisibilityHelper.fragmentIsVisible(ChatFragment.fragmentClassName)) {
                            ChatFragment.chatsList.add(newChatMessage);
                            ChatFragment.chatsList.notifyDataSetChanged();
                        } else {
                            notificationHelper.internalNotification(getBaseContext(), newChatMessage);
                        }
                    }
                }

            });
        }
    }

};
  

Основное действие (как создаются фрагменты)

 @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().requestFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
    setContentView(R.layout.activity_main);

    Bundle extras = getIntent().getExtras();

    initializeDataSources();
    setLastContactUpdate();

    if(usersDataSource.getCurrentUser() == null)
    {
        Intent LoginActivity = new Intent(getApplicationContext(), LoginActivity.class);
        LoginActivity.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(LoginActivity);
        finish();
    }
    else
    {
        if(localServiceBinder == null)
            localServiceBinder = new LocalServiceBinder();

        bindLocalService();

        runDispatchMethod(extras, savedInstanceState);

        if (savedInstanceState == null) {
            getAndSaveUserDetails();
            GCMRegistrationID = registerGCM();
        }
    }
}

protected void runDispatchMethod(Bundle extras, Bundle savedInstanceState) {
    if(savedInstanceState == null) {
        startFragment(new ChatsFragment(), false);
    }

    if(extras != null amp;amp; extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM) != null amp;amp; !extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM).equals("")) {
        getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
        startFragment(new ChatsFragment(), false);

        ChatFragment chatFragment = new ChatFragment();
        Bundle chatExtras = (Bundle) new Bundle();
        chatExtras.putString(ConstantHelper.RECEIVED_MESSAGES_FROM, extras.getString(ConstantHelper.RECEIVED_MESSAGES_FROM));
        chatFragment.setArguments(chatExtras);
        startFragment(chatFragment);
        return;
    }
}

public void startFragment(Fragment newFragment) {
    startFragment(newFragment, true);
}

public void startFragment(Fragment newFragment, Boolean addToBackstack) {
    if(addToBackstack) {
        getFragmentManager().beginTransaction().replace(R.id.container, newFragment, newFragment.getClass().getName()).addToBackStack(newFragment.getClass().getName()).commit();
    } else {
        getFragmentManager().beginTransaction().replace(R.id.container, newFragment, newFragment.getClass().getName()).commit();
    }

    getFragmentManager().executePendingTransactions();
}
  

Адаптер чатов

 public class ChatsAdapter extends BaseAdapter {

private List<Chat> chats;
private LayoutInflater inflater;
private String emptyLastMessageValue;

public ChatsAdapter(Context context, List<Chat> chats) {
    this.chats = chats;
    this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    emptyLastMessageValue = context.getText(R.string.fragment_chats_chat_created).toString();
}

@Override
public int getCount() {
    return chats.size();
}

@Override
public Chat getItem(int position) {
    return chats.get(position);
}

@Override
public long getItemId(int position) {
    return chats.get(position).getId();
}

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

    View chatAdapterView = convertView;

    if(convertView == null)
        chatAdapterView = inflater.inflate(R.layout.adapter_chats, null);

    TextView layout_fullname = (TextView) chatAdapterView.findViewById(R.id.fullname);
    TextView layout_last_message = (TextView) chatAdapterView.findViewById(R.id.last_message);
    TextView layout_unread_messages = (TextView) chatAdapterView.findViewById(R.id.unread_messages);
    TextView layout_last_message_datetime = (TextView) chatAdapterView.findViewById(R.id.last_message_datetime);

    Chat row = chats.get(position);

    String firstname = row.getContact().getFirstname();
    String fullname = row.getContact().getFullname();

    if(firstname == null || firstname.equals(""))
        fullname = StringHelper.ucfirst(row.getContact().getUsername());

    layout_fullname.setText(fullname);

    String last_message_value;
    String last_message_datetime_value = "";
    if(row.getLastMessage() == null) {
        last_message_value = emptyLastMessageValue;
        layout_last_message_datetime.setVisibility(TextView.GONE);
        layout_unread_messages.setVisibility(TextView.GONE);
    } else {
        last_message_value = row.getLastMessage().getMessageBody();

        last_message_datetime_value = DateHelper.toReadableDatetime(row.getLastMessage().getMessageDatetime());
        layout_last_message_datetime.setText(last_message_datetime_value);

        Integer unreadMessages = row.getUnreadMessages();
        if(unreadMessages > 0) {
            layout_unread_messages.setText(String.valueOf(unreadMessages));
            layout_unread_messages.setVisibility(TextView.VISIBLE);
        } else {
            layout_unread_messages.setVisibility(TextView.GONE);
        }
    }

    layout_last_message.setText(last_message_value);

    return chatAdapterView;
}

}
  

Функция обновления списка чатов

 public void refreshChatsList() {
    Log.d("DEBUG", "It does come here!");
    chats.clear();
    chats.addAll(((MainActivity) getActivity()).chatsDataSource.getAllChats());
    chats_adapter.notifyDataSetChanged();
}
  

Вывод Logcat

 07-06 20:12:43.892: D/SMACK(14948): 08:12:43 PM RCV  (1106735848): <message id="3jRRg-24" to="tijme@192.168.137.1" type="chat" from="test@192.168.137.1/Smack"><body>Test</body></message>

07-06 20:12:43.962: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment

07-06 20:12:43.962: D/DEBUG(14948): REFRESHING

07-06 20:12:43.962: D/DEBUG(14948): It does come here!

07-06 20:12:48.406: D/SMACK(14948): 08:12:48 PM RCV  (1106735848): <message id="3jRRg-25" to="tijme@192.168.137.1" type="chat" from="test@192.168.137.1/Smack"><body>Test 2</body></message>

07-06 20:12:48.446: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment

07-06 20:12:51.059: D/KUTZOOI(14948): HELEMAAL WÄCK

07-06 20:12:51.099: D/dalvikvm(14948): GC_FOR_ALLOC freed 161K, 3% free 9653K/9912K, paused 19ms, total 21ms

07-06 20:12:51.109: I/dalvikvm-heap(14948): Grow heap (frag case) to 13.272MB for 4000016-byte allocation

07-06 20:12:51.139: D/dalvikvm(14948): GC_FOR_ALLOC freed 1K, 2% free 13558K/13820K, paused 25ms, total 25ms

07-06 20:12:54.953: D/SMACK(14948): 08:12:54 PM RCV  (1106735848): <message id="3jRRg-26" to="tijme@192.168.137.1" type="chat" from="test@192.168.137.1/Smack"><body>Test 3</body></message>

07-06 20:12:54.993: D/DEBUG(14948): nl.test.messatch.fragments.ChatsFragment

07-06 20:12:54.993: D/DEBUG(14948): REFRESHING

07-06 20:12:54.993: D/DEBUG(14948): It does come here!
  

Список чатов
Просмотр списка чатов

Уведомление
Уведомление в чате

Комментарии:

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

2. Нет. Я использую findFragmentByTag для поиска фрагмента, а findFragmentByTag не возвращает null, поэтому он находит фрагмент. Конечно, это должно быть то же самое…

3. Можете ли вы опубликовать код адаптера?

4. предложение @Luksprog кажется разумным. Не могли бы вы добавить конструктор без аргументов к вашему фрагменту списка чатов, записав его hashCode()? Посмотрите, сколько экземпляров этого фрагмента создается, когда действие возобновляется из-за nofitication, просто чтобы быть уверенным. В зависимости от того, как, где и когда вы добавляете фрагменты, может случиться так, что в итоге вы получите два экземпляра одного и того же фрагмента, один поверх другого, и тот, который вы изменяете, будет покрыт, но тот, который не изменен. И еще: меня тошнит от использования ваших статических переменных.

5. @GiulioPiancastelli Аааа, я вижу два разных хэш-кода после открытия уведомления. Что я могу с этим поделать? Не могли бы вы объяснить, как избежать статических переменных? Я немного новичок в Android!

Ответ №1:

Убедитесь, что вы работаете с тем же фрагментом после возврата к действию, нажав на уведомление (судя по тому, как появляется проблема). Если вы не сохраняете ссылку на тот же экземпляр, который видит пользователь, то любое обновление чата завершится с ошибкой, поскольку вы будете обновлять только фоновый фрагмент (а не видимый). Ошибка, по-видимому, заключается в том, runDispatchMethod() что вы каждый раз выполняете транзакцию с новым фрагментом, не проверяя, доступен ли уже другой экземпляр ChatsFragment (в этом случае вы бы просто вызвали метод обновления для этого экземпляра).

Ответ №2:

(Я бы добавил комментарий, если бы мог)

Я думаю, что проблема заключается в notifyingdatasetChanged();

Добавьте это в свой адаптер

 public void swapItems(List<Chat> chat) {
    this.chats = chat;
    notifyDataSetChanged();
}
  

Вызывайте это для новых сообщений

 chats_adapter.swapItems(((MainActivity) getActivity()).chatsDataSource.getAllChats());