我有这个活动。活动内部我有3个asynctask,我需要其中一个在onCreate方法中执行。我想在这个网站http://www.androidhive.info/2013/11/android-working-with-action-bar/上实现一个刷新按钮教程(几乎在最后),但问题是我想让动作栏刷新按钮执行asynctask,这是首先在onCreate方法中调用。示例活动:
package info.androidhive.actionbar;
import info.androidhive.actionbar.model.SpinnerNavItem;
import info.androidhive.info.actionbar.adapter.TitleNavigationAdapter;
import java.util.ArrayList;
import android.app.ActionBar;
import android.app.Activity;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.SearchView;
public class MainActivity extends Activity implements
ActionBar.OnNavigationListener {
// action bar
private ActionBar actionBar;
// Refresh menu item
private MenuItem refreshMenuItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new SyncData.execute(); //this is example of my implementation I call my asynctask here
actionBar = getActionBar();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
....
}
/**
* On selecting action bar icons
* */
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Take appropriate action for each action item click
switch (item.getItemId()) {
...
case R.id.action_refresh:
// refresh
refreshMenuItem = item;
// load the data from server
new SyncData().execute();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
/**
* Async task to load the data from server
* **/
private class SyncData extends AsyncTask<String, Void, String> {
@Override
protected void onPreExecute() {
// set the progress bar view
refreshMenuItem.setActionView(R.layout.action_progressbar);
refreshMenuItem.expandActionView();
}
@Override
protected String doInBackground(String... params) {
// not making real request in this demo
// for now we use a timer to wait for sometime
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(String result) {
refreshMenuItem.collapseActionView();
// remove the progress bar view
refreshMenuItem.setActionView(null);
}
};
}
在本教程中输入
refreshMenuItem.setActionView(R.layout.action_progressbar);
我被卡住了对refreshMenuItem的空引用。有解决办法吗?
是的,有。当你在onCreate(..)
中运行AsyncTask
时,你的MenuItem
还没有初始化——当用户按下相应的按钮时,由于一些奇怪的原因,它被初始化了,这发生在onOptionsItemSelected()
中。这就是为什么你得到你的NullPointerException
。
要避免这种情况,请在onPrepareOptionsMenu(..)
或onCreateOptionsMenu(..)
中初始化MenuItem
。
public boolean onPrepareOptionsMenu(Menu menu){
refreshMenuItem = menu.findItem(R.id.action_refresh);
return true;
}
Upd但更重要的是您应该在哪里执行AsyncTask
。只有当Activity
使用的所有类成员都处于"安全状态"时,才应该执行;我的意思是,如果你的Activity
有SomeObject someObj
成员,并且你从AsyncTask
中调用someObj.setSometh()
,你依赖于这样的假设,你的someObj != null
.
因此,首先由您选择何时运行AsyncTask
。