我正在编写一个程序,它返回一个字符串的ArrayList。问题是,当我调用方法时,列表尚未填充,所以我得到一个空列表。
我尝试了一个线程,但现在我在调用方法时得到一个null
引用。顺便说一下,我必须实现异步任务,否则在尝试使用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;
}
}
答案 0 :(得分:1)
你这样做完全错了。 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;
}
}
然后在你的另一堂课:
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
}
});
}
答案 1 :(得分:1)
Artur您在代码中所做的是启动一个线程来检索设备列表,然后启动另一个线程(AsyncTask)来实际创建设备列表。所以你有三个线程同时在这里运行(假设你在UIThread中使用DeviceManager类)。 getDeviceList()
返回 null 的原因是因为AsyncTasks doInBackground
尚未运行以收集您的设备列表,因此可能正在等待其计划的机会。所以得出结论,你只需要一个线程(UIThread除外),它可以是一个线程或AsyncTask(更好,因为它提供了更好的控制),因为生锈的大脑已经在他的回答中使用了。我更喜欢将DeviceManager设置为AsyncTask(只是设备管理器的唯一任务是检索设备列表),如下面的代码所示。
in AsyncTask doInBackground
在后台线程中运行(顾名思义),onPostExecute
在doInBackground
之后的UI线程上运行
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");
答案 2 :(得分:0)
您正在获取空数组列表,因为当您使用异步任务获取数组列表和异步任务时,doINBackground方法在不同的线程上运行(意味着不在主线程上)。因此,当您的程序运行时,您的程序不会等待异步任务响应。
你可以这样解决这个问题...... 在异步任务类中使用onPostExecute方法并返回arraylist
@Override
protected void onPostExecute(Void result) {
//return array list here
getList();
}
希望这会对你有所帮助
答案 3 :(得分:0)
首先,您不需要将DeviceManager作为线程,因为您在getDeviceList中运行的任务将在另一个新线程中启动。秒你不应该等待主(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;
}
}