如何在AsyncTask运行时禁用Button? (机器人)

时间:2015-04-21 20:30:15

标签: android button android-asynctask

我正在尝试在执行下载任务时禁用按钮。我尝试过使用setEnabled,setVisibility和setClickable。我想我尝试了这些选项的所有组合。所有这些都在任务执行时禁用了按钮单击事件,但事件仍在某种程度上被注册,当我响应按钮时,如果我在禁用时单击按钮,则会调用处理程序...即使它是隐形或"走了"! (不确定它是否被称为处理程序,我想引用onClick方法)。

我还插入了一个计数器和一个日志来验证我上面所说的内容。代码如下所示。这段代码if(counter>1) return;旨在阻止崩溃,但我想将其删除,因为我想重新启用该按钮,而不是永久禁用它。

的onClick:

public void downloadOnClick(View v) {
    counter++;
    Log.d(this.getLocalClassName(), "Button was clicked " + counter + " times.");
    if(counter>1) return;

    ConnectivityManager connMgr = (ConnectivityManager)
            getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {
        //mButton.setVisibility(View.GONE);
        mButton.setEnabled(false);
        //mButton.setClickable(false);
        mTextView.setText("Getting html file...");
        // if we use simple http, we will need to handle redirect status code
        new DownloadWebpageTask().execute("https://www.google.com/");
    } else {
        mTextView.setText("No network connection available.");
    }
}

的AsyncTask:

private class DownloadWebpageTask extends AsyncTask<String, Void, String> {

    private HttpURLConnection mConnection;

    @Override
    protected String doInBackground(String... urls) {
        try {
            URL url = new URL(urls[0]);
            mConnection = (HttpURLConnection) url.openConnection();
            mConnection.setReadTimeout(10000 /* milliseconds */);
            mConnection.setConnectTimeout(15000 /* milliseconds */);
            mConnection.setRequestMethod("GET");
            mConnection.setDoInput(true);

            mConnection.connect();
            int statusCode = mConnection.getResponseCode();
            if (statusCode != HttpURLConnection.HTTP_OK) {
                return "Error: Failed getting update notes";
            }

            return readTextFromServer(mConnection);

        } catch (IOException e) {
            return "Error: " + e.getMessage();
        }
    }

    private String readTextFromServer(HttpURLConnection connection) throws IOException {
        InputStreamReader stream = null;
        try {
            stream = new InputStreamReader(connection.getInputStream());
            BufferedReader br = new BufferedReader(stream);
            StringBuilder sb = new StringBuilder();
            String line = br.readLine();
            while (line != null) {
                sb.append(line + "\n");
                line = br.readLine();
            }
            return sb.toString();
        } finally {
            if (stream != null) {
                stream.close();
            }
        }
    }

    @Override
    protected void onPostExecute(String result) {
        mTextView.setText(result);
        // Can not reactivate button / cancel (pending?) events....
        //mButton.setVisibility(View.VISIBLE);
        mButton.setEnabled(true);
        //mButton.setClickable(true);
    }
}

完整的项目(非常简单,只是一个训练示例)可以在我刚刚创建的repository中进行测试。

总而言之,根据我的阅读,实际上存在关于按钮禁用的问题。大多数情况下,只有在标志为true时才通过使用标志来解析onClick方法。虽然,这并没有解决重新启用按钮的问题。我也试过mButton.cancelPendingInputEvents();但是它不起作用(我不知道为什么。点击事件尚未注册?或者它们没有待处理?

这个问题有一个简单的解决方案吗?有任何想法吗?我错过了一些基本细节吗?如果没有,我正在考虑尝试以编程方式创建一个新按钮以解决问题。如果我不保留对旧按钮的引用,是否通过垃圾回收删除了它们?

提前致谢!

[编辑]澄清:

由于标题在这一点上可能会产生误导,我想澄清我能够禁用并重新启用该按钮,所有功能都可以,除非禁用了按钮。请注意,我添加了行if(counter>1) return;只是为了测试,但它会停止按钮按照我想要的方式工作(这就是为什么我没有使用旗帜。我不想要这条线当我解决问题时,在那里!)。该日志足以告诉我,当按钮重新启用时正在调用该方法,因为我在禁用时点击了它

2 个答案:

答案 0 :(得分:2)

我发现,在您的示例中,AsyncTask的完成速度非常快,以至于Button由于被禁用而无法点击,因此时间非常短。所以,它基本上是一个时间问题。

我发现通过将Button的重新启用延迟4秒,它可以按预期工作。

请注意,通过直观显示此更改,Button会在填充TextView后重新启用。{/ p>

以下是onPostExecute()中的代码更改:

        @Override
        protected void onPostExecute(String result) {
            mTextView.setText(result);

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {

                @Override
                public void run() {
                    //re-enable the button
                    mButton.setEnabled(true);

                }
            }, 4000);
        }

请注意,您可以删除计数器逻辑,它现在应该按预期工作:

public void downloadOnClick(View v) {

    Log.d(this.getLocalClassName(), "Button was clicked");

    ConnectivityManager connMgr = (ConnectivityManager)
            getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) {

        mButton.setEnabled(false);

        mTextView.setText("Getting html file...");
        // if we use simple http, we will need to handle redirect status code
        new DownloadWebpageTask().execute("https://www.google.com/");
    } else {
        mTextView.setText("No network connection available.");
    }
}

答案 1 :(得分:0)

错误在于:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="DOWNLOAD TEXT"
    android:id="@+id/button"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true"
    android:onClick="downloadOnClick" />

您缺少 OnClickListener 的概念!首先,你必须以这种方式修改上面的xml删除onClick属性:

<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="DOWNLOAD TEXT"
    android:id="@+id/button"
    android:layout_alignParentTop="true"
    android:layout_alignParentLeft="true"
    android:layout_alignParentStart="true" />

您必须修改Activity onCreate方法才能在按钮上设置OnClickListener:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mTextView = (TextView) findViewById(R.id.text);
    mButton = (Button) findViewById(R.id.button);
    mButton.setOnClickListener(new View.OnClickListener() {
         public void onClick(View v) {
            counter++;
            Log.d(this.getLocalClassName(), "Button was clicked " + counter + " times.");
            if(counter>1) return;

            ConnectivityManager connMgr = (ConnectivityManager)
                    getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
            if (networkInfo != null && networkInfo.isConnected()) {
                mButton.setEnabled(false);
                mTextView.setText("Getting html file...");
                // if we use simple http, we will need to handle redirect status code
                new DownloadWebpageTask().execute("https://www.google.com/");
            } else {
                mTextView.setText("No network connection available.");
            }
         }
     });
}

这是处理点击的正确方法。

查看更多内容:

<强>此外:

从我的角度来看,最好的方法是在Activity上实现OnClickListener():

public class MyActivity extends Activity implements View.OnClickListener {
}

通过这种方式,您可以为需要设置OnClickListener的每个按钮编写:

buttonX.setOnClickListener(this);
buttonY.setOnClickListener(this);
buttonZ.setOnClickListener(this);

在Activity onClick()中,您必须覆盖OnClickListener方法,因此:

@Override
public void onClick(View v) {
    if(v.getId() == R.id.ButtonX)){
        //do here what u wanna do.
    } else if(v.getId() == R.id.ButtonY){
        //do here what u wanna do.
    } else if(v.getId() == R.id.ButtonZ){
        //do here what u wanna do.
    }
}

同样在onClick中,您可以使用view.getId()获取资源ID,然后在开关/案例块中使用它来识别每个按钮并执行相关操作。