I am writing a programm that returns me a ArrayList of Strings. Problem is, when I call the method the list is not filled yet so I get an empty list back .
I tried it with a thread but now I get a null
reference when I call the method. By the way i had to implement a async task, otherwise I get an exception when trying to use InetAddress
.
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;
}
}
Artur what you are doing in your code is starting a thread to retrieve device list and then another thread(AsyncTask) to actually creates the device list. So you have three threads running here simultaneously (assuming you are using DeviceManager class in UIThread). The reason getDeviceList()
is returning null is because AsyncTasks doInBackground
hasn't run yet to collect your device list it might be waiting for its chance to get scheduled. so to conclude that, you just need one thread(other than UIThread), it can either be a Thread or AsyncTask (more preferable as it gives better control) as rusted brain has used in his answer. I prefer to make DeviceManager as AsyncTask (just a bit cleaner and if device managers only task is to retrieve device list) as code below.
in AsyncTask doInBackground
runs in a background thread(as name suggests) and onPostExecute
runs on the UI thread after 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);
}
}
}
so in your activity you can call
new DeviceManager(new DeviceManager.ConnectionCompleteListener
() {
@Override
public void onSuccess(List<String> deviceList) {
}
@Override
public void onFailure() {
}
}).execute("YOUR_NETWORK_IP");