2015-09-28 2 views
-2

Я пытаюсь запустить свой проект и когда я иду, чтобы отправить сообщение, я получаю эту ошибку: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 раза!

ответ

0

Вы пытаетесь получить 5-й элемент в списке, в котором есть только 4 элемента. Беда приходит из этой строки кода

if (null == noteList || !nd.equals(noteList.get(incomingNotesLength - 1))) { 

Особенно noteList.get(incomingNotesLength - 1))

Это не удается, потому что incomingNotesLength инициализируется incomingNotes.length();, не noteList.size().

Если вы пытаетесь получить последний элемент в noteList, вы должны изменить эту строку кода

if (null == noteList || !nd.equals(noteList.get(noteList.size() - 1))) { 

или

int noteListLength = noteList.size(); 
if (null == noteList || !nd.equals(noteList.get(noteListLength - 1))) { 
+1

Хорошо, так я изменить код, чтобы: ' if (null == noteList ||! nd.equals (noteList.get (noteList.length() - 1))) { noteList = новый ArrayList <> (incomingNotesLength); ' –

+0

Есть много способов исправить эту тривиальную вопрос; как вы это решаете, зависит от вас. Вы понимаете проблему с вашим исходным кодом? – mittmemo

+0

Я понимаю, но он не распознает .length в noteList.length() –

Смежные вопросы