对于我的应用程序,我想禁用/更改按下的特定按钮。
我有一个名为btnClicked的onclick方法,其简化形式如下:
Public class MainActivity extends Activity{
Button myBytton;
@Override
protected void onCreate(Bundle savedInstanceState) {
myBytton = (Button)findViewById(R.id.buttonCall);
}
public void btnClicked(View view)
{
myBytton.setText("loading");
myBytton.setEnabled(false);
myBytton.setClickable(false);
// Do a call to an external api
callApi();
}
public void callApi(){
// run querys
if(succesullyCalledApi){
vibrator.vibrate(500);
// I tried commenting out the below part,
// it is than visible that the phone vibrates before it
// has changed the text (atleast a quarter of a second).
myBytton.setText("search");
myBytton.setEnabled(true);
myBytton.setClickable(true);
}
}
}
在callApi方法中是一种振动方法,该振动方法在函数获得结果后振动。
另外,如果在结果中启用了callApi myButton,则文本更改为搜索。
发生了以下情况:
我单击按钮,手机先振动,然后改变文本。
我的问题。
为什么callApi / vibrate在myBytton.setText之前运行?
最佳答案
奈杰尔克所说的是真的。
当您到达btnClicked
方法时,所有说明均在UI线程上进行。因此,当您要求系统振动时,系统将被锁定XX次,具体取决于您传递给方法vibrator.vibrate(XX);
的时间。
为了避免这种“冻结”,您需要使另一个线程振动。
这是它的样子:
Public class MainActivity extends Activity
{
Button myBytton;
@Override
protected void onCreate(Bundle savedInstanceState)
{
myBytton = (Button)findViewById(R.id.buttonCall);
}
public void btnClicked(View view)
{
myBytton.setText("loading");
myBytton.setEnabled(false);
myBytton.setClickable(false);
// Do a call to an external api
callApi();
}
public void callApi()
{
// run querys
if(succesullyCalledApi)
{
// here you create and run the Thread.
// put anything you want to do inside the run method
new Thread(
new Runnable()
{
public void run()
{
// here you start the vibration
vibrator.vibrate(500);
}
}
).start();
// I tried commenting out the below part,
// it is than visible that the phone vibrates before it
// has changed the text (atleast a quarter of a second).
myBytton.setText("search");
myBytton.setEnabled(true);
myBytton.setClickable(true);
}
}
}
就是这样。它将启动另一个线程,该线程将处理振动并且不会冻结UI线程。
编辑
这是AsyncTask版本:
扩展AsyncTask时询问的三个元素是:
您传递给
doInBackground()
方法的参数类型在
onProgressUpdate()
方法中传递的元素的类型。doInBackground()
方法返回的元素的类型,也是onPostExecute()
方法的参数。看起来是这样的:
public class MyTask extends AsyncTask<Void, Integer, Boolean>
{
private Button mButton;
public MyTask(Button button)
{
mButton = button;
}
// Here everything will run on a background Thread
protected Boolean doInBackground(Void... voids)
{
boolean succesullyCalledApi = false;
// do your long querys here
// ...
return succesullyCalledApi;
}
// Here everything will run on the UI Thread
protected void onProgressUpdate(Integer... progress) {
// here you can make some update to the UI like updating a
// progress bar
}
// Here everything will run on the UI Thread
protected void onPostExecute(Boolean succesullyCalledApi)
{
if(succesullyCalledApi)
{
mButton.setText("search");
mButton.setEnabled(true);
mButton.setClickable(true);
// here you start the vibration
vibrator.vibrate(500);
}
}
}
在您的
callApi()
方法中,您只需要这样做:public void callApi()
{
new MyTask(myButton).execute();
}
编辑2
为了将查询检索回您的主线程(或UI线程),您所要做的就是……什么都没有。
调用
onPostExecute()
方法时,您位于UI线程中。但我假设您想将查询取回MainActivity。为此:
在MyTask构造函数的参数中传递MainActivity,
在MainActivity中创建一个名为
processQuery()
的方法(或任何您想要的方法),最后,在
onPostExecute()
方法中调用此方法。以下是一些摘要:
Public class MainActivity extends Activity
{
Button myBytton;
...
public void callApi()
{
// add this to the constructor
new MyTask(this, myButton).execute();
}
// I put String here but adapt it to your query Type.
public void processQuery(String query)
{
// process your query here.
}
}
public class MyTask extends AsyncTask<Void, Integer, Boolean>
{
private Button mButton;
private MainActivity mMainActivity;
public MyTask(MainActivity mainActivity, Button button)
{
mButton = button;
mMainActivity = mainActivity;
}
...
// Here everything will run on the UI Thread
protected void onPostExecute(Boolean succesullyCalledApi)
{
if(succesullyCalledApi)
{
// process your query
mMainActivity.processQuery("THE QUERY YOUR WANT TO PROCESS");
mButton.setText("search");
mButton.setEnabled(true);
mButton.setClickable(true);
// here you start the vibration
vibrator.vibrate(500);
}
}
}
也许有更好的方法可以做到这一点,但这很简单并且可以工作:)
希望能帮助到你。
干杯