2014-03-19 117 views
0

我有這個活動。內部活動我有3個asynctask,我需要其中的一個在onCreate方法中執行。我想按照這個網站上的教程http://www.androidhive.info/2013/11/android-working-with-action-bar/(幾乎在最後)實現一個刷新按鈕,但問題是我想要操作欄刷新按鈕來執行asyncTask,它首先在onCreate方法中調用。例如活動:何時執行asynctask

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); 

下面這個教程我stucked與空引用refreshMenuItem。有解決方法嗎?

回答

1

是的,有。當您在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的班級成員處於「安全狀態」時,你才應該執行;通過這個,我的意思是,如果你的ActivitySomeObject someObj成員,並且你從AsyncTask內撥打someObj.setSometh(),那麼你就依靠這個假設,即你的someObj != null

因此,您首先應該選擇何時運行AsyncTask

+0

是的,我給了那個asynctask一些條件,它現在的作品:) –

+0

很高興爲你,要小心,'活動'的生命週期是一件困難的事情,有很多事情要考慮:) – Drew