如何让程序等待 java 中的方法

How to make a program wait for a method in java

我正在编写一个程序,returns 我是一个字符串数组列表。问题是,当我调用该方法时,列表尚未填充,所以我得到一个空列表。 我用一个线程试过了,但现在我在调用该方法时得到了一个 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;
    }
}

您得到的数组列表是空的,因为当您使用异步任务获取数组列表时,异步任务 doINBackground 方法在不同的线程上运行(意味着不在主线程上)。因此,当您的程序运行时,您的程序不会等待异步任务响应。

你可以这样解决... 在异步任务 class 和 return arraylist

中使用 onPostExecute 方法
@Override
protected void onPostExecute(Void result) {
 //return array list here
getList();
}

希望对您有所帮助

你完全错了。 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;
    }
}

然后在你的另一个 class:

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

首先,您不需要将 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;
}



}

Artur 您在代码中所做的是启动一个线程来检索设备列表,然后启动另一个线程 (AsyncTask) 来实际创建设备列表。所以你同时在这里有三个线程 运行ning(假设你在 UIThread 中使用 DeviceManager class)。 getDeviceList() 返回 null 的原因是因为 AsyncTasks doInBackground 尚未 运行 收集您的设备列表,它可能正在等待机会得到安排。因此得出结论,您只需要一个线程(UIThread 除外),它可以是 Thread 或 AsyncTask(更可取,因为它提供更好的控制),因为 rusted brain 在他的回答中使用了。我更喜欢将 DeviceManager 设置为 AsyncTask(只是更简洁一点,如果设备管理器的唯一任务是检索设备列表)如下代码。

in AsyncTask doInBackground 运行s 在后台线程中(顾名思义)和 onPostExecute 运行s 在 UI 线程之后 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);
        }
    }
}

所以在你的 activity 中你可以调用

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

        }

        @Override
        public void onFailure() {

        }
    }).execute("YOUR_NETWORK_IP");