Я пытаюсь запустить свой проект и когда я иду, чтобы отправить сообщение, я получаю эту ошибку:java.lang.IndexOutOfBoundsException: Invalid индекс 4, размер 4 Ошибка
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: FATAL EXCEPTION: main
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: Process: com.clarkawilson.quarkposts, PID: 22976
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: java.lang.IndexOutOfBoundsException: Invalid index 4, size is 4
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at java.util.ArrayList.get(ArrayList.java:308)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.clarkawilson.quarkposts.fragments.NotesFragment.updateMessageList(NotesFragment.java:177)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.clarkawilson.quarkposts.handler.PostHandler.processRequestResult(PostHandler.java:261)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.clarkawilson.quarkposts.handler.PostHandler.access$000(PostHandler.java:35)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.clarkawilson.quarkposts.handler.PostHandler$1.onResponse(PostHandler.java:205)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.clarkawilson.quarkposts.handler.PostHandler$1.onResponse(PostHandler.java:202)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:60)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.android.volley.toolbox.StringRequest.deliverResponse(StringRequest.java:30)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.android.volley.ExecutorDelivery$ResponseDeliveryRunnable.run(ExecutorDelivery.java:99)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at android.os.Looper.loop(Looper.java:145)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6837)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1404)
09-28 20:33:40.591 22976-22976/com.clarkawilson.quarkposts E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1199)
09-28 20:33:42.161 22976-22976/com.clarkawilson.quarkposts I/Process: Sending signal. PID: 22976 SIG: 9
NoteFragment:
public void updateMessageList(JSONObject jsonObject){
try {
/* The elements of incomingNotes are added into the noteList in reverse order,
* i.e. treat incoming notes like a stack, so that the message we view at the
* bottom of our adapter, is the last message received by the server.
*
* The second evaluation in the if statement tests whether the last element in
* noteList is the same at the first element in the incoming list from the server.
* If they're different, this means that new messages have been posted on the server.
* If they're the same, nothing has changed. Don't traverse incomingList.*/
JSONArray incomingNotes = jsonObject.getJSONArray(PostHandler.TAG_POSTS);
NoteData nd = new NoteData(incomingNotes.getJSONObject(0));
int incomingNotesLength = incomingNotes.length();
if (null == noteList || !nd.equals(noteList.get(incomingNotesLength - 1))) {
noteList = new ArrayList<>(incomingNotesLength);
for (int i = incomingNotesLength - 1; i >= 0; i--) {
JSONObject c = incomingNotes.getJSONObject(i);
NoteData noteData = new NoteData(c);
noteList.add(noteData);
}
updateMessageList();
}
}
catch (JSONException e) {
e.printStackTrace();
Toast.makeText(activity,
ERROR_GENERAL + ": " + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
PostHandler:
public class PostHandler {
public static final String SERVER_DIRECTORY = "http://-------/";
public static final String IMAGES_DIRECTORY = "uploadedimages/";
public static final String DEFAULT_AVATAR = "ic_action_camera";
public static final String READ_NOTES_URL = SERVER_DIRECTORY + "notes.php";
public static final String POST_NOTES_URL = SERVER_DIRECTORY + "addnote.php";
public static final String LOGIN_URL = SERVER_DIRECTORY + "login.php";
public static final String REGISTER_URL = SERVER_DIRECTORY + "register.php";
public static final String UPLOAD_IMAGE = SERVER_DIRECTORY + "upload_image.php";
public static final String TAG_POSTS = "posts";
public static final String TAG_SUCCESS = "success";
public static final String IMAGE_TYPE = ".PNG";
public static final String LOGIN_USERNAME_PASSWORD_ERROR ="Username/password combination not registered.";
public static final String REGISTER_SUCCESS = "Successfully registered";
public static final String REGISTER_USERNAME_ERROR = "Username taken, try a different one!";
private static final String SERVER_ERROR = "Unexpected error from server, try updating app.";
public static String getDefaultAvatarUrl(){
return SERVER_DIRECTORY + IMAGES_DIRECTORY + DEFAULT_AVATAR + IMAGE_TYPE;
}
/* Converts the avatar image into a String to be posted with the JSON request */
public static String encodeBitmap(Bitmap bitmap){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byte_arr = stream.toByteArray();
return Base64.encodeToString(byte_arr, 0);
}
/* Singleton instance, getter, and private constructor */
private static PostHandler singletonInstance;
public static PostHandler getSingletonInstanceSetSuperFragment(SuperFragment superFragment) {
if (null == singletonInstance)
singletonInstance = new PostHandler();
singletonInstance.setSuperFragment(superFragment);
return singletonInstance;
}
private PostHandler(){}
private static AppController appController = AppController.getInstance();
private static ImageLoader imageLoader = appController.getImageLoader();
private SuperFragment superFragment;
private NotesFragment notesFragment;
private ProgressDialog pDialog;
private String username, password;
private Bitmap avatarBitmap;
/* Private so user can only work with one fragment at a time, thus not allowed to
* have any other combination of superFragment and notesFragment other than the following:
* superFragment == notesFragment OR notesFragment == null */
private void setSuperFragment(SuperFragment superFragment){
if(pDialog != null) pDialog.dismiss();
this.superFragment = superFragment;
if(superFragment instanceof NotesFragment)
this.notesFragment = (NotesFragment)superFragment;
else
this.notesFragment = null;
}
/* Sets the PostHandler's bitmap, but does not upload it. */
public void setAvatarBitmap(Bitmap b){
avatarBitmap = b;
if(hasNotesFragment()) postAvatar(b);
}
/* If username not yet submitted, return default avatar url. */
public String getUsernameAvatarUrl(){
return getUsernameAvatarUrl(username);
}
public static String getUsernameAvatarUrl(String username){
if(null != username) return SERVER_DIRECTORY + IMAGES_DIRECTORY + username + IMAGE_TYPE;
return getDefaultAvatarUrl();
}
private boolean hasNotesFragment(){return null != notesFragment;}
public boolean hasUsername(){return null != username && !username.isEmpty();}
public String getUsername() {return username;}
public static AppController getAppController() {return appController;}
public static ImageLoader getImageLoader() {return imageLoader;}
public static void clearImageCache(){appController.clearCache();}
/* Username and password are only modifiable externally by these public post methods
* to maintain consistent login information across all fragments using the handler. */
public void postLogin(String username, String password){
this.username = username;
this.password = password;
postLogin();
}
public void postMessage(String username, String message){
this.username = username;
postMessage(message);
}
public void postRegister(String username, String password){
this.username = username;
this.password = password;
postRegister();
}
public void updateNotesFragmentMessages(){
if(hasNotesFragment())
attemptGet(READ_NOTES_URL, false);
}
private void postAvatar(Bitmap b){
String encodedString = encodeBitmap(b);
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("image", encodedString);
attemptPost(UPLOAD_IMAGE, params, false);
}
private void postLogin(){
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
attemptPost(LOGIN_URL, params, true);
}
private void postMessage(String message){
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("message", message);
attemptPost(POST_NOTES_URL, params, false);
}
private void postRegister(){
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
attemptPost(REGISTER_URL, params, true);
}
/* Creates a dialog to indicate that work is being done.*/
private void createProgressDialog(){
pDialog = new ProgressDialog(superFragment.getActivity());
pDialog.setMessage("Working...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(true);
pDialog.show();
}
private void attemptGet(String url, boolean useProgressDialog){
attemptHTTP(Request.Method.GET, url, new HashMap<String, String>(), useProgressDialog);
}
private void attemptPost(String url, HashMap<String,String> params, boolean useProgressDialog){
attemptHTTP(Request.Method.POST, url, params, useProgressDialog);
}
/* Sends a post/get request using the Google Volley library's queue. */
private void attemptHTTP(int method, String url,
final HashMap<String,String> params,
boolean useProgressDialog){
if(useProgressDialog) {
createProgressDialog();
}
StringRequest postRequest = new StringRequest(method, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
processRequestResult(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
}) {
@Override
protected Map<String, String> getParams()
{return params;}
};
AppController.getInstance().addToRequestQueue(postRequest);
}
/* Decide what to do after server responds to attemptHTTP call. Server replies with an int
* response encoded by its .php files; here we decode this response. */
private void processRequestResult(String response){
try {
JSONObject jsonResponse = new JSONObject(response);
int result = jsonResponse.getInt(TAG_SUCCESS);
pDialog.dismiss();
switch (result) {
case 0: // username password combination error
Toast.makeText(superFragment.getActivity(),
LOGIN_USERNAME_PASSWORD_ERROR, Toast.LENGTH_SHORT).show();
break;
case 1: // login successful
if (null != avatarBitmap) postAvatar(avatarBitmap);
else superFragment.loadNotesFragment();
break;
case 2: // registration success
Toast.makeText(superFragment.getActivity(),
REGISTER_SUCCESS, Toast.LENGTH_SHORT).show();
postAvatar(avatarBitmap);
break;
case 3: // username already registered
Toast.makeText(superFragment.getActivity(),
REGISTER_USERNAME_ERROR, Toast.LENGTH_SHORT).show();
break;
case 4: // avatar successfully uploaded
if(hasNotesFragment()) notesFragment.updateMessageListAvatars();
else superFragment.loadNotesFragment();
break;
case 5: // message successfully posted
if(hasNotesFragment()) updateNotesFragmentMessages();
break;
case 6: // messages list successfully returned
if(hasNotesFragment()) {notesFragment.updateMessageList(jsonResponse);}
break;
default: break;
}
}
catch (JSONException e) {
Toast.makeText(superFragment.getActivity(), SERVER_ERROR, Toast.LENGTH_SHORT).show();
}
}
}
Любая помощь с этим была бы признательна. Я уверен, что я, вероятно, пропустил немного кода, хотя я проверил его 3 или 4 раза!
Хорошо, так я изменить код, чтобы: ' if (null == noteList ||! nd.equals (noteList.get (noteList.length() - 1))) { noteList = новый ArrayList <> (incomingNotesLength); ' –
Есть много способов исправить эту тривиальную вопрос; как вы это решаете, зависит от вас. Вы понимаете проблему с вашим исходным кодом? – mittmemo
Я понимаю, но он не распознает .length в noteList.length() –