简体   繁体   English

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

[英]How to make a program wait for a method in java

I am writing a programm that returns me a ArrayList of Strings. 我正在编写一个程序,该程序返回一个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. 我用线程尝试过,但是现在我在调用该方法时得到一个null引用。 By the way i had to implement a async task, otherwise I get an exception when trying to use InetAddress . 顺便说一下,我必须实现一个异步任务,否则在尝试使用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;
    }
}

You are doing it completely wrong. 您所做的完全错误。 A Thread runs in the background and so does AsyncTask , so basically you are making a background task run in background. Thread在后台运行, AsyncTask也在后台运行,因此基本上您是在后台运行后台任务。 Inception . 盗梦空间

Try this: 尝试这个:

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

Then in your other 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
        }
    });
}

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. Artur您在代码中所做的工作是启动一个线程以检索设备列表,然后启动另一个线程(AsyncTask)以实际创建设备列表。 So you have three threads running here simultaneously (assuming you are using DeviceManager class in UIThread). 因此,您有三个线程在此处同时运行(假设您正在UIThread中使用DeviceManager类)。 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. getDeviceList()返回null的原因是因为AsyncTasks doInBackground尚未运行以收集您的设备列表,它可能正在等待其安排机会。 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. 因此得出的结论是,您只需要一个线程(UIThread除外),它可以是Thread或AsyncTask(更可取,因为它可以提供更好的控制),就像生锈的大脑在他的答案中使用的那样。 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. 我更喜欢将DeviceManager设置为AsyncTask(只是更简洁一些,如果仅设备管理器的任务是检索设备列表),如下所示。

in AsyncTask doInBackground runs in a background thread(as name suggests) and onPostExecute runs on the UI thread after doInBackground 在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);
        }
    }
}

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

You are getting empty array list because as you are using async task for getting array list and async task doINBackground method runs on different thread(means not on main thread). 您正在获取空数组列表,因为在使用异步任务获取数组列表和异步任务时,doINBackground方法在不同的线程上运行(意味着不在主线程上)。 So when your program runs then your program doesn't wait for async task response. 因此,当您的程序运行时,您的程序就不会等待异步任务响应。

You can solve this like that... Use onPostExecute method in async task class and return the arraylist 您可以这样解决...在异步任务类中使用onPostExecute方法并返回arraylist

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

Hope this will help you 希望这个能对您有所帮助

First of All you don't need to make DeviceManager a thread as the task which you are running in getDeviceList will start in another new thread. 首先,您不需要使DeviceManager成为线程,因为您在getDeviceList中运行的任务将在另一个新线程中启动。 Second You shouldn't wait on main(UI) thread so instead of waiting callback is a better mechanism. 其次,您不应该在main(UI)线程上等待,因此最好是等待回调,而不是等待回调。

If you insist on the same code try this.. 如果您坚持使用相同的代码,请尝试此操作。

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



}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM