从 AsyncTask 显示 Toast 直到事件发生

Display Toast from AsyncTask until event occurs

我想使用 Toast 显示 "Connecting ..." 直到 设备连接到新网络(更具体地说,当获得 IP 地址时,请参阅 while 循环在下面的 doInBackground 中)。我正在使用 AsyncTask 连接到网络,但是如果我将 Toast.makeText(...).show() 放在 onProgressUpdate() 中,toast 调用将堆叠并最终以比预期更长的时间显示文本。我的连接 class:

public class Connect extends AsyncTask<Object,Void,Void>{
    private static final String TAG="sure2015test";
    private Context context;
    private Network network;
    @Override
    protected Void doInBackground(Object... params) {

        this.network=(Network)params[0];
        this.context=(Context) params[1];
        final WifiConfiguration conf = new WifiConfiguration();
        conf.SSID = "\"" + network.ssid + "\"";
        if(network.password!=null){
            conf.preSharedKey = "\""+ network.password +"\"";
        }
        else{
            conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
        }

        if(network.manager.addNetwork(conf)==-1){
            Log.i(TAG, "Add network fail");
        }
        List<WifiConfiguration> configs = network.manager.getConfiguredNetworks();
        for (WifiConfiguration i : configs) {
            if (i.SSID != null && i.SSID.equals("\"" + network.ssid + "\"")) {
                network.manager.disconnect();
                if(network.manager.enableNetwork(i.networkId, true)==false){
                    Log.i(TAG,"Enable Network fail ");
                }
                if(network.manager.reconnect()==false) {
                    Log.i(TAG, "Reconnect fail");
                }
            }
        }
        WifiInfo info=network.manager.getConnectionInfo();
        while((info.getIpAddress())==0){
            //Wait until non-zero IP address (once a non-zero ip address is obtained, you are connected to the network)
            //Tried to use NetworkInfo.DetailedState to check if it was CONNECTED
            //However the api method said it remained in OBTAINING_IPADDR state even after it obtained an ip (must be bug)
            info=network.manager.getConnectionInfo();
            publishProgress();
            Log.i(TAG,"IP "+info.getIpAddress());
            try{
                Thread.sleep(100);
            }
            catch(InterruptedException e){
                Log.i(TAG,"Interrupted exception");
            }
        }
        return null;
    }


    @Override
    protected void onProgressUpdate(Void... values) {
        Toast.makeText(context, "Connecting ...", Toast.LENGTH_SHORT).show();
        super.onProgressUpdate(values);
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        Toast.makeText(context,"Connected",Toast.LENGTH_SHORT).show();
        Intent newActivity = new Intent(context, Device.class);
        newActivity.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        newActivity.putExtra("Device", network.ssid);
        context.startActivity(newActivity);
        super.onPostExecute(aVoid);
    }
}

我建议使用 ProgressDialog 而不是 Toast。您可以在 运行 之前显示它 AsyncTask 并隐藏它 onPostExecute。它看起来像.-

ProgressDialog dialog = ProgressDialog.show(CurrentActivity.this, "", "Connecting...", true, false);

[...]

dialog.dismiss();

顺便说一句,不要忘记将字符串文字放入 Strings 资源文件中 :)

吐司不是显示工作进度的好习惯。 Toast 旨在显示次要信息和快速信息(例如,在您的情况下是显示设备已连接),但我认为最好在布局中实现 ProgressBar 并将其设置为可见,同时 AsyncTask执行 doInBackground 并在 onPostExecute.

中设置为不可见

如果你需要在另一个线程中显示 Toast,也在 doInBackground(Object...params) 中,你可以使用:

YourActivity.this.runOnUiThread(new Runnable() {
    public void run() {
        //put here your thread
    }
});

但是,在这种情况下,您需要获取上下文。我用静态变量来做。但不要忘记,Toast 只出现很短的时间,您无法管理它。如果你需要一直显示消息,你可以使用 ProgressDialog