2014-11-29 2 views
0

Недавно я начал изучать развитие Android (новичок в java), и в настоящее время я работаю над приложением чата/мессенджераПочему ListView обновляется только при прокрутке на устройстве, но отлично работает на виртуальном устройстве?

Проблема, с которой я столкнулся, как говорится в заголовке, заключается в том, что список, в котором отображаются сообщения показаны не обновляется на устройстве, если не прокручивается, но он отлично работает на виртуальной машине. Пока что я тестировал только LG Optimus l5 II, но мне все равно нужно это исправить.

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

В 2 нити я добавил, что может привести к этому:

  1. Проверяет состояние соединения и, если отсоединены пытается восстановить соединение.
  2. Тема, используемая для связи с сервером.

Я тестировал запуск только со второй резьбой, и проблема все еще возникает.

Я хочу указать, что в первый раз я пробую что-то вроде этого (сервер-клиент, многопоточность, java, android (я все еще в колледже, и они не учат нас этим вещам там)), и не располагал документацией о том, как мне настроить связь между сервером и клиентом. Это самый эффективный способ, о котором я мог думать.

это в конце onCreate:

StartConnectingRoutine(); // so you know where it all starts 

и код для него:

private void StartConnectingRoutine() 
    { 
     Thread t = new Thread() 
     { 
      @Override 
      public void run() 
      { 
       while(true) 
       { 
        if(!connected) 
        { 
         if(connect != null) 
         { 
          if(!connect.isAlive()) 
          { 
           ConnectListener(); 
          } 
         } 
         else 
         { 
          ConnectListener(); 
         } 
        } 
        try { 
         sleep(CONNECTION_CHECK_TIME_MS); // this is set to 10000 (10 seconds) 
        } catch (InterruptedException e) { 
         Log.e("Intrerrupted", e.toString()); 
        } 
       } 
      } 
     }; 
     t.start(); 
    } 

и connectListener():

private void ConnectListener() 
{ 
    Log.d("Connecting", "Connecting..."); 
    connect = new Thread() 
    { 
     JSONObject info = new JSONObject(); 
     String receivedMessage; 
     @Override 
     public void run() 
     { 
      try { 
       info.put("Name", user.GetName()); 
       info.put("PORT", MY_PORT); 
       info.put("IPv4", getIpAddress()); 
      } catch (JSONException e1) { 
       Log.e("JSON", "JSON error: " + e1.toString()); 
      } 
      try 
       { 
        ServerSocket = new Socket(SERVER_IP, SERVER_PORT); 
        dis = new DataInputStream(ServerSocket.getInputStream()); 
        dos = new DataOutputStream(ServerSocket.getOutputStream()); 

        dos.writeUTF(info.toString()); 
        dos.flush(); 
        String response = dis.readUTF(); 
        if(response.equals("connected")) 
          { 
           Log.d("Connect", "Connected!"); 
           connected = true; 
          } 
         else 
          Log.d("Connect", "Failed to connect!"); 
        while(connected) 
        { 
         receivedMessage = dis.readUTF(); 

         DisplayNewMessage(new MMessage(receivedMessage, MMessage.MessageType.Received));       
        } 

       }catch(SocketException e) 
       { 
        try { 
         if(connected) 
         { 
           ServerSocket.close(); 
           dis.close(); 
           dos.close(); 
          connected = false; 
         } 
        } catch (IOException e1) { 
         // TODO Auto-generated catch block 
         e1.printStackTrace(); 
        } 

       } 
       catch(Exception e) 
       { 
        Log.d("Connect", "Failed to connect"); 
        Log.e("Connect", e.toString()); 
        connected = false; 
       } 

     } 
    }; 

    connect.start(); 
} 

Исправлено:

Повторное подключение потока (я также попытался использовать asyncTask для этого, но он не откроет другую asyncTask, даже если бы я попытался открыть его из onProgressUpdate(), который, как предполагается, сможет запускать компоненты потока ui):

private void startConnectingRoutine() 
    { 
     Thread t = new Thread() 
     { 
      @Override 
      public void run() 
      { 
       Log.d("ConnectingRoutine", "Started connecting routine."); 
       while(true) 
       { 
        if(!connected) 
        { 
         startListener(); 
        } 
        try { 

         sleep(CONNECTION_CHECK_TIME_MS); 
        } catch (InterruptedException e) { 
         Log.e("Intrerrupted", e.toString()); 
        } 
       } 
      } 
     }; 
     t.start(); 
    } 

Слушатель нить:

private void startListener() 
{ 
    new Listener().execute(); 
} 

.

private class Listener extends AsyncTask<Long, String, Long> 
    { 

     @Override 
     protected Long doInBackground(Long... params) { 
      Log.d("Connecting...", "Connecting..."); 
      JSONObject info = new JSONObject(); 
      String receivedMessage; 
       try { 
        info.put("Name", user.GetName()); 
        info.put("PORT", MY_PORT); 
        info.put("IPv4", getIpAddress()); 
       } catch (JSONException e1) { 
        Log.e("JSON", "JSON error: " + e1.toString()); 
       } 
       try 
        { 
         serverSocket = new Socket(SERVER_IP, SERVER_PORT); 
         dis = new DataInputStream(serverSocket.getInputStream()); 
         dos = new DataOutputStream(serverSocket.getOutputStream()); 

         dos.writeUTF(info.toString()); 
         dos.flush(); 
         String response = dis.readUTF(); 
         if(response.equals("connected")) 
           { 
            Log.d("Connect", "Connected!"); 
            connected = true; 
           } 
          else 
           Log.d("Connect", "Failed to connect!"); 
         while(connected) 
         { 
          receivedMessage = dis.readUTF(); 
          publishProgress(receivedMessage); 

         }    
        } 
        catch(Exception e) 
        { 
         Log.d("Connect", "Failed to connect"); 
         Log.e("Connect", e.toString()); 
         return null; 
        } 
        return null; 
     } 

     @Override 
     protected void onProgressUpdate(String... values) { 
      super.onProgressUpdate(values); 
      displayNewMessage(new MMessage(values[0], MMessage.MessageType.Received)); 
     } 

     @Override 
     protected void onPostExecute(Long result) { 
      super.onPostExecute(result); 

      connected = false; 
      try{ 
      if(serverSocket != null) 
       serverSocket.close(); 
      if(dis != null) 
       dis.close(); 
      if(dos != null) 
       dos.close(); 
      }catch(Exception e) 
      { 
       Log.e("Listener", "There was a problem closing the connection: " + e.toString()); 
      } 
     } 
    } 
+0

Хорошо, поэтому я сделал обновление, и теперь он отлично работает. Таким образом, проблема была №1. Сказал Пол Ламмерцма. Используя asyncTask, onProgressUpdate() устранила проблему. Я добавлю код в конце моего вопроса, чтобы другие могли видеть проблему и ответ в том же месте. – laurGanta

+0

Еще раз спасибо Paul Lammertsma – laurGanta

ответ

0

Есть, возможно, несколько вещей происходит здесь не так, но два, которые выскакивают являются:

  1. Вы звоните DisplayNewMessage() снаружи в потоке пользовательского интерфейса.
  2. Вы не уведомляете адаптер о том, что его набор данных был изменен.

Я призываю вас заглянуть в лучшие механизмы для выполнения задач в фоновом режиме, чем просто создавать Thread. Использование AsyncTasks было бы хорошим началом, но вам нужно будет проявлять особую осторожность, чтобы справляться с задачами между изменениями конфигурации (такими как вращение устройства).

Кроме того, ваш код очень трудно читать, когда вы используете имена методов. Это противоречит соглашениям Java. Вы облегчите себе задачу, аккуратно форматируя свой код (с этим хорошо справляется IDE) и учатся следовать правилам!

+0

notifyDataSetChanged() вызывается в addItem() из адаптера. Я начну пытаться следовать конвенциям. Я некоторое время программировал на C#, и там мы использовали заглавные имена функций. Спасибо за ваш совет. – laurGanta

+0

Я попробую использовать AsyncTasks для 2 потоков, как вы сказали, и я опубликую обновление, когда закончу. – laurGanta

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