NigelK 说的是真的。
当您到达该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);
}
}
}
可能有更好的方法来做到这一点,但这个方法简单且有效:)
希望能帮助到你。
干杯