2016-04-13 23 views
0

içinde bir yöntem için bekliyorum Bana bir ArrayList dizeleri döndüren bir program yazıyor. Sorun, yöntem çağrıldığında liste henüz doldurulmadığı için boş bir liste geri aldım. Bir iş parçacığı ile denedim, ancak yöntemi çağırdığımda şimdi bir null başvurusu alıyorum. Bu arada bir async görevini uygulamak zorunda kaldım, aksi halde InetAddress'u kullanmaya çalışırken bir istisna alıyorum. Eğer dizi listesi ve zaman uyumsuz görev doINBackground yöntemini almak için zaman uyumsuz görev kullandığınız olarak çünküBir program nasıl yapılır java

private class DeviceManager extends Thread { 

    private ArrayList<String> deviceList; 
    private String networkIP; 

    public DeviceManager(String networkIP) { 
     this.networkIP = networkIP; 
    } 

    public void run() { 
     getDeviceList(); 
    } 

    public ArrayList<String> getDeviceList() { 
     new AsyncTask<Void, Void, Void>() { 

      @Override 
      protected Void doInBackground(Void... params) { 
       try { 
        deviceList = new ArrayList<String>(); 
        InetAddress address; 

        Log.i("NetworkIPgetDeviceList", networkIP); 

        String deviceIP = networkIP; 

        for (int i = 0; i < 255; i++) { 
         address = InetAddress.getByName(deviceIP += "" + i); 
         if (address.isReachable(2000)) {  
          Log.i("Devicefound", deviceIP); 
          deviceList.add(deviceIP); 
         } 
         deviceIP = networkIP; 
        } 

       } catch (UnknownHostException e) { 
        e.printStackTrace(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
       return null; 
      } 
     }.execute(); 
     return deviceList; 
    } 

    public ArrayList<String> getList() { 
     return this.deviceList; 
    } 
} 
+0

Kaçmalısın çağırabilir Bu listeyi daha sonra başka bir senkronizasyon görevinde kullanan kod – Ferrybig

+0

C# ile deneyime sahibim ve nasıl bir async yöntemi uygulayarak bu sorunu çözmek için basit bir yol olduğunu hatırladım, ama javada eşdeğer olmadığını biliyorum :( –

+0

Async görevinin tamamlanmasını bekliyorsanız, yine de aynı özel durumu elde edersiniz. Android bu istisna atar neden, Eğer ana iş parçacığı asmak Eğer app tamamen yanlış yapıyoruz kötü kullanıcı deneyimi – Ferrybig

cevap

1
sonra başka iş parçacığı (AsyncTask) aslında cihazı oluşturur ne aygıt listesine almak için bir iş parçacığı başlatılıyor kodunuzda yapıyoruz ve

Artur liste. Yani aynı anda burada çalışan üç parçanız var (UIThread'de DeviceManager sınıfını kullandığınızı varsayarak). getDeviceList()'un numaralı numaralı telefona dönmesinin nedeni, AsyncTasks doInBackground henüz cihaz listenizi almak için çalışmadığı için planlanmış olma şansını bekliyor olabilir. Bu nedenle, sadece bir iş parçacığına (UIThread dışında) ihtiyacınız olduğu sonucuna varmak için, bir Thread veya AsyncTask (daha iyi kontrol sağladığı için daha çok tercih edilir) paslı beyin cevabında kullanmıştır. DeviceManager'ı AsyncTask (sadece biraz daha temiz ve sadece aygıt yöneticileri sadece aygıt listesi almak ise) olarak kod yapmayı tercih ederim.

AsyncTask bir arka plan iş parçacığı doInBackground çalışır (adından da anlaşılacağı gibi) ve UI iş parçacığı üzerinde onPostExecute çalışır böylece aktivitesinde doInBackground

class DeviceManager extends AsyncTask<String, Void, List<String>> { 

    private ConnectionCompleteListener listener; 

    public interface ConnectionCompleteListener { 
     void onSuccess(List<String> deviceList); 

     // if you need to know reason for failure you can add 
     // parameter to onFailure 
     void onFailure(); 
    } 

    public DeviceManager(ConnectionCompleteListener listener) { 
     this.listener = listener; 
    } 

    @Override 
    protected List<String> doInBackground(String... params) { 
     List<String> deviceList = new ArrayList<>(); 
     String networkIP = params[0]; 
     try { 
      InetAddress address; 
      Log.i("NetworkIPgetDeviceList", networkIP); 

      String deviceIP = networkIP; 
      for (int i = 0; i < 255; i++) { 
       address = InetAddress.getByName(deviceIP += "" + i); 
       if (address.isReachable(2000)) { 
        Log.i("Devicefound", deviceIP); 
        deviceList.add(deviceIP); 
       } 
       deviceIP = networkIP; 
      } 
     } catch (IOException e) { 
      deviceList = null; 
      e.printStackTrace(); 
     } 
     return deviceList; 
    } 

    @Override 
    protected void onPostExecute(List<String> deviceList) { 
     if (deviceList == null) { 
      this.listener.onFailure(); 
     } else { 
      this.listener.onSuccess(deviceList); 
     } 
    } 
} 

sonra

new DeviceManager(new DeviceManager.ConnectionCompleteListener 
      () { 
     @Override 
     public void onSuccess(List<String> deviceList) { 

     } 

     @Override 
     public void onFailure() { 

     } 
    }).execute("YOUR_NETWORK_IP"); 
+0

teşekkür ederim bunu bitirdim :))) –

0

Sen boş dizi listesi elde (değil ana iş parçacığı üzerinde anlamına gelir) farklı bir iş parçacığı üzerinde çalışır. Programınız çalıştığında, programınız eşzamansız görev yanıtını beklemez.

Sen tamamen yanlış yapıyor bu size

+0

Sorun, Ana Kalıcımdan bir InetAddress Yöntemini çağırmayı denedim. Bu bir istisna oluşturdu ve bunu çözmek için bir asenkron uygulamam gerekiyordu. –

+0

OnPostExecute'u nerede uygulamak zorundayım? Ana Kalıtımımda mı? –

+0

cevap için teşekkürler, ben async görevleri konuları ve onPostExecute hakkında daha fazla bilgi almak için bazı dökümanlar okuyacağım –

1

yardımcı olacaktır zaman uyumsuz görev sınıfında o ... Kullanım OnPostExecute yöntemiyle gibi bu çözmek ve ArrayList

@Override 
protected void onPostExecute(Void result) { 
//return array list here 
getList(); 
} 

Umut döndürebilir. Bir Thread arka planda çalışır ve AsyncTask yapar, bu nedenle temelde arka planda çalışan bir arka plan görevi yapıyorsunuz. Inception.

bu deneyin:

public class DeviceManager { 

    private ArrayList<String> deviceList; 
    private String networkIP; 
    private ConnectionCompleteListener listener; 

    public interface ConnectionCompleteListener { 
     void onSuccess(); 

     void onFailure(); 
    } 

    public void setConnectionCompleteListener(ConnectionCompleteListener listener) { 
     this.listener = listener; 
    } 

    public DeviceManager(String networkIP) { 
     this.networkIP = networkIP; 
    } 

    public void getDeviceList() { 
     new AsyncTask<Void, Void, Boolean>() { 

      @Override 
      protected void onPostExecute(Boolean result) { 
       if(result) listener.onSuccess(); 
       else listener.onFailure(); 
      } 

      @Override 
      protected Boolean doInBackground(Void... params) { 
       try { 
        deviceList = new ArrayList<String>(); 
        InetAddress address; 

        Log.i("NetworkIPgetDeviceList", networkIP); 

        String deviceIP = networkIP; 

        for (int i = 0; i < 255; i++) { 
         address = InetAddress.getByName(deviceIP += "" + i); 
         if (address.isReachable(2000)) { 
          Log.i("Devicefound", deviceIP); 
          deviceList.add(deviceIP); 
         } 
         deviceIP = networkIP; 
        } 
        return true; 
       } catch (UnknownHostException e) { 
        e.printStackTrace(); 
        return false; 
       } catch (IOException e) { 
        e.printStackTrace(); 
        return false; 
       } 
       return null; 
      } 
     }.execute(); 
    } 

    public ArrayList<String> getList() { 
     return this.deviceList; 
    } 
} 

Sonra başka sınıfında:

Eğer DeviceManager sen getDeviceList içinde çalışan görev olarak bir iplik yapmak gerekmez All
private class classname{ 
    DeviceManager manager=new DeviceMnager(networkIp); 
    manger.setConnectionCompleteListener(new DeviceManager.ConnectionCompleteListener() { 
     @Override 
     public void onSuccess() { 
      // get your list here 
      manager.getList(); 
     } 

     @Override 
     public void onFailure() { 
      // connection failed show error 
     } 
    }); 
} 
+0

Dinleyici yöntemlerini çağırırsanız doInBackground'dan arka plan iş parçacığında çalışır. Bu geri bildirimler için onPostExecute kullanın – Shashank

+0

@Shashank güzel yakalamak! düzenlendi. Çalışması gereken –

+0

. sadece bir not, eğer Artur sadece bu listeyi almak için cihaz yöneticisi kullanıyorsa, neden DeviceManager sınıfını bir AsyncTask yapmıyorsunuz ve geri çağırma yapıyorsanız neden devicelist yerine manager.getList(); – Shashank

0

İlk olacak Başka bir yeni konuya başlamak. İkincisi Ana (UI) iş parçacığı beklememelisiniz, beklemek yerine beklemek daha iyi bir mekanizmadır.

aynı kod ısrar ederse bu deneyin ..

public class DeviceManager extends Thread { 
private ArrayList<String> deviceList; 

private String networkIP; 
private boolean dataAvailable; 

public DeviceManager(String networkIP) { 
    this.networkIP = networkIP; 
} 

public void run() { 
    getDeviceList(); 
} 

public ArrayList<String> getDeviceList() { 

    new AsyncTask<Void, Void, Void>() { 
     @Override 
     protected Void doInBackground(Void... params) { 
      try { 
       deviceList = new ArrayList<String>(); 
       InetAddress address; 

       Log.i("NetworkIPgetDeviceList", networkIP); 

       String deviceIP = networkIP; 

       for (int i = 0; i < 255; i++) { 
        System.out.println("checking " + i); 
        address = InetAddress.getByName(deviceIP += "" + i); 
        if (address.isReachable(2000)) { 

         Log.i("Devicefound", deviceIP); 

         deviceList.add(deviceIP); 
        } 
        deviceIP = networkIP; 
       } 

      } catch (UnknownHostException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
      dataAvailable = true; 
      synchronized (DeviceManager.this) { 
       DeviceManager.this.notify(); 
      } 
      return null; 
     } 

    }.execute(); 

    return deviceList; 
} 

synchronized public ArrayList<String> getList() { 

    while (!dataAvailable) { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
     } 

    } 
    return this.deviceList; 
} 



} 
İlgili konular