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

时间:2016-04-13 09:03:21

标签: java android java-threads

我正在编写一个程序,它返回一个字符串的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;
    }
}

4 个答案:

答案 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在后​​台线程中运行(顾名思义),onPostExecutedoInBackground之后的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;
}



}