Проблема с областью возврата ArrayList в методе, содержащем запрос залпа - PullRequest
0 голосов
/ 20 января 2019

Я пытался использовать этот вопрос в качестве примера, но я не знал, куда идти с ним, так как я никогда не видел его раньше.

Я получаю сообщения с сервера, которые будут отображаться в RecyclerView. Каждое сообщение - это новый экземпляр класса Message, который я создал. Если я жестко закодирую новые сообщения, они отображаются нормально, однако самая странная часть заключается в том, что жестко закодированные и реальные сообщения затем отображаются вместе. Закомментируйте жестко закодированные сообщения, и все они исчезнут.

Вот скриншоты, используя list.add и затем удаляя его:

С включенным в список list.add () (два поддельных и два реальных сообщения) enter image description here

Без ручного удаления list.add () enter image description here

Вот класс:

public class MessagesActivity extends AppCompatActivity {

private RecyclerView messages;
private RecyclerView.Adapter adapter;
private static final String TAG = "MessagesActivity";
private static final String getMessagesUrl = "https://my_server_url.net/includes/api/mobile_get_messages.php";
private SharedPreferences sharedPreferences;
private static String username;
private static ProgressDialog messagesProgressDialog;
private static ArrayList<Message> list = new ArrayList<>();
private static JSONObject jsonObject;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_messages);
    messagesProgressDialog = new ProgressDialog(MessagesActivity.this, R.style.Custom_Progress_Dialog);
    messagesProgressDialog.setIndeterminate(true);
    messagesProgressDialog.setMessage("Fetching Messages...");
    messagesProgressDialog.show();
    sharedPreferences = this.getSharedPreferences("MyPref", MODE_PRIVATE);
    username = sharedPreferences.getString("username", null);
    messages = findViewById(R.id.messages);
    messages.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));

    ArrayList<Message> messages = initMessages();
    /*
    Tried to use this from the aforementioned link shown above, 
    but didn't know where to go with it.
    */
    //ArrayList<Message> messages = initMessages(new Callback() {
    //    @Override
    //    public void onSuccess(ArrayList<Message> list) {

    //    }
    //});

    RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(this);
    this.messages.setLayoutManager(mLayoutManager);

    adapter = new MessageAdapter(messages);
    this.messages.setAdapter(adapter);
}

//The currently used method declaration
private ArrayList<Message> initMessages() {

//My attempt to use the suggestion in the link as the method declaration.
//private ArrayList<Message> initMessages(final Callback onCallBack) {
    RequestQueue messagesQueue = Volley.newRequestQueue(this);
    StringRequest messagesRequest = new StringRequest(Request.Method.POST, getMessagesUrl, new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            messagesProgressDialog.dismiss();
            try {
                String baseUrl = "https://my_server_url.net";
                String defaultbaseUrl = "https://my_server_url.net/css/images/user_default/default_avatar.png";
                JSONObject responseObject = new JSONObject(response);
                Log.d(TAG, "Response: "+response);
                JSONArray responseArray = responseObject.getJSONArray("data");
                for(int i = 0; i < responseArray.length(); i++) {
                    jsonObject = responseArray.getJSONObject(i);
                    String avatar = jsonObject.getString("avatar");
                    String message = jsonObject.getString("message");
                    String sender = jsonObject.getString("sender");
                    String timestamp = jsonObject.getString("timestamp");
                    /*
                    Determine if avatar will be user's avatar, or default avatar (they haven't uploaded a new one yet)
                     */
                    if(avatar.contains("../users")) {
                        String substring = avatar.substring(avatar.indexOf(".") + 2);
                        avatar = baseUrl+substring;
                    } else {
                        avatar = defaultbaseUrl;
                    }
                    /*
                    Add each new Message to the list to display
                    They are getting added to the list, but later the
                    list returns 0 for the size.
                     */
                    list.add(new Message(sender, message, avatar, timestamp));
                    //Attempt to use suggestion in link
                    //onCallBack.onSuccess(list);
                    Log.d(TAG, "Messages List Length: "+list.size());
                }
            } catch(Exception e) {
                Log.d(TAG, "EXCEPTION: "+e.getMessage());
            }
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            ToastMaker.createLongToast(getApplicationContext(), "VolleyError: "+error.getMessage());
            messagesProgressDialog.dismiss();
        }
    }) {
        @Override
        public Map<String, String> getParams() {
            Map<String, String> params = new HashMap<>();
            params.put("username", username);
            return params;
        }
    };
    messagesQueue.add(messagesRequest);
    /*
    THIS IS RETURNING 0 FOR THE LIST SIZE :(
     */
    Log.d(TAG, "List Size at bottom of method: "+list.size());
    /*
    Manually adding elements shows the items correctly in RecyclerView, but not by adding them from the response
     */
    //list.add(new Message("testuser", "Hello. This is a fake message", "https://my_server_url.net/css/images/user_default/default_avatar.png", "10:00 pm"));
    //list.add(new Message("testuser2", "Hello. This is another fake message", "https://my_server_url.net/css/images/user_default/default_avatar.png", "12:37 pm"));
    return list;
}
//Suggestion from the link. Currently not used.
//public interface Callback {
//    void onSuccess(ArrayList<Message> list);
//}

}

Вот журналы, показывающие, что я получаю правильный ответ:

D/MessagesActivity: Response: {"data":[{"has_read":"yes","avatar":"css\/images\/user_default\/default_avatar.png","sender":"*************","message":"the time is still off","timestamp":"2018-12-12 08:57 PM"},{"has_read":"yes","avatar":"..\/users\/testuser\/uploads\/281007997_1546828047.jpeg","sender":"testuser","message":"Hello, *********. I'm testuser. I like writing code too. ","timestamp":"2018-11-13 08:24 PM"}],"count":2}

Вот Log.d () внизу метода:

D/MessagesActivity: List Size at bottom of method: 0

Но вот операторы Log.d () после добавления каждого нового объекта Message:

D/MessagesActivity: Messages List Length: 1
D/MessagesActivity: Messages List Length: 2

Как я могу исправить эту проблему? Все мои данные там.

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Если у кого-то есть лучшее предложение, пожалуйста, не стесняйтесь. Я обнаружил этот ответ по аналогичной проблеме, и при его реализации это работает. Он показывает правильные сообщения из базы данных. Я создал метод updateData () прямо под моим методом initMessages (), вот так:

public void updateData() {
    ArrayList<Message> strs = new ArrayList<>();
    for(int i = 0; i < list.size(); i++) {
        strs.add(list.get(i));
        RecyclerView.Adapter updateAdapter = new MessageAdapter(list);
        messages = findViewById(R.id.messages);
        messages.setAdapter(updateAdapter);
        Log.d(TAG, "updateData() called, List Size: "+list.size());

    }
}

Затем, в конце моего onResponse(String response) метода, я просто добавил вызов метода:

        /*
        Add each new Message to the list to display
        */
        list.add(new Message(sender, message, avatar, timestamp));
        Log.d(TAG, "Messages List Length: "+list.size());
    }
    updateData(); //<--- Call the method here. It's working!
} catch(Exception e) {
    Log.d(TAG, "EXCEPTION: "+e.getMessage());
}

Снимок экрана, показывающий, что сообщения правильно извлекаются и отображаются

enter image description here

Вот журналы из оператора Log.d() в конце updateData()

D/MessagesActivity: updateData() called, List Size: 2
D/MessagesActivity: updateData() called, List Size: 2

Так что, хотя это и "работает" само по себе, если у кого-то есть лучшее предложение, которое будет следовать правильному соглашению о коде (если применимо), не стесняйтесь, дайте мне знать. В противном случае это работает.

Редактировать : мне пришлось переопределить onBackPressed () из-за дублирования списка при возврате к предыдущему действию и повторной загрузке MessagesActivity. Неужели так:

@Override
public void onBackPressed() {
    super.onBackPressed();
    list.clear();
}
0 голосов
/ 20 января 2019

Хорошо в коде я вижу две проблемы на первый взгляд.

  1. Вы не предоставляете адаптеру list для привязки вида.
  2. Когда вы получаетеновое сообщение вы не уведомляете адаптер о том, что было добавлено новое сообщение.

Проблема 1:

Если вы этого еще не сделали (или, возможно, удалилив приведенном выше коде) вы должны предоставить список адаптеру, вызвав соответствующий метод, например adapter.setAdapterList().

Проблема 2:

Когда вы получаете новыйДля сообщения просто позвоните adapter.notifyItemInserted(), и это обеспечит создание новым адаптером ViewHolder / View.

...