2016-04-13 10 views
0

私はStringListのArrayListを返すプログラムを書いています。問題は、私がメソッドを呼び出すと、リストはまだ埋められていないので、空のリストが戻ってくる。 私はスレッドで試しましたが、メソッドを呼び出すとnullの参照を取得しました。ところで、私は非同期タスクを実装する必要がありました。それ以外の場合は、InetAddressを使用しようとすると例外が発生します。プログラムを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

を呼び出すことができますあなたは実行する必要があります後で別の同期タスクでこのリストを使用するコード – Ferrybig

+0

私はC#での経験があり、非同期メソッドを実装することでこの問題を解決する簡単な方法があったのですが、 :( –

+0

非同期タスクが完了するのを待っている場合でも、同じ例外が発生します。理由はアンドロイドが例外をスローした場合、メインスレッドをハングアップするとアプリケーションが応答しなくなり、悪いユーザーエクスペリエンスにつながるということです。 – Ferrybig

答えて

1

アルトゥールは、デバイスのリストを取得するために、スレッドを開始し、その後、別のスレッド(AsyncTaskは)実際にデバイスを作成するために、これを試してくださいリスト。したがって、ここでは3つのスレッドが同時に実行されています(UIThreadでDeviceManagerクラスを使用していると仮定します)。理由getDeviceList()nullを返すのは、AsyncTasks doInBackgroundがデバイスリストを収集するためにまだ実行されていないために、スケジュールされる機会を待っている可能性があるからです。それで、あなたはちょうどスレッド(UIThread以外)が1つだけ必要であると結論付けるには、の錆びた脳であるが彼の答えに使用されているように、スレッドまたはAsyncTask(より良い制御を与えるので、より好ましい)私は以下のコードでDeviceManagerをAsyncTask(ちょっとクリーナーにし、デバイスマネージャのみのタスクでデバイスリストを取得する場合)としたいと思います。doInBackground

後AsyncTaskバックグラウンドスレッドで doInBackground実行する(名前の通り)とUIスレッド上 onPostExecute実行中

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); 
     } 
    } 
} 

ので、あなたの活動にあなたが

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

     } 

     @Override 
     public void onFailure() { 

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

ありがとうございます:))) –

0

あなたは配列リストと非同期タスクdoINBackground方法が異なるスレッド上で実行され得るための非同期タスクを使用しているとして(メインスレッド上にないこと)ので、あなたは空の配列リストを取得しています。したがって、プログラムが実行されるとき、プログラムは非同期のタスク応答を待たない。

は、あなたが完全に間違ってそれをやっている、これはあなたに

+0

問題は、私はMainActivityからInetAddressメソッドを呼び出そうとしました。これは例外を引き起こし、私はこれを解決するためにasynctaskを実装しなければなりませんでした。 –

+0

どこでonPostExecuteを実装する必要がありますか?私のMainActivityでは? –

+0

ちょっと答えてくれてありがとう、私は非同期タスクのスレッドとonPostExecuteに関する詳細な情報を得るためにいくつかのドキュメントを読むでしょう –

1

を支援する非同期タスククラスでその... 使用onPostExecute方法のようにこの問題を解決し、ArrayListのに

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

希望を返すことができます。 A Threadはバックグラウンドで実行されるので、AsyncTaskもあります。基本的に、バックグラウンドでバックグラウンドタスクを実行しています。 インセプション

この試してみてください:あなたの他のクラスに続いて

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; 
    } 
} 

を:あなたはデバイス・マネージャあなたがgetDeviceList意志で実行されているタスクとしてスレッドにする必要はありませんすべての

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

リスナーメソッドdoInBackgroundからバックグラウンドスレッドで実行されます。これらのコールバックにはonPostExecuteを使用してください。 – Shashank

+0

@Shashank nice catch!編集されました。 –

+0

が必要です。なぜなら、ArturがDevice Managerを使ってそのリストを取得しているのであれば、DeviceManagerクラスをAsyncTaskにしないと、コールバック関数を使用して、代わりにdevicelistを提供するのはなぜでしょうか。 – Shashank

0

ファースト別の新しいスレッドで開始します。 Secondメイン(UI)スレッドを待つべきではないので、コールバックを待機するのではなく、より良いメカニズムです。

あなたは同じコードを主張した場合..あなたがあなたのコード内で何をしているか

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; 
} 



} 
関連する問題