我得到了NullPointerException,我无法弄清楚出了什么问题。我试过只带上必要的代码。 我有3个类:MainActivity,GoogleCommunicator和CustomAdapter。 该错误是由CustomAdapter中的跟随引起的:
mActivity.updateBought(position, "1");
我得到的错误是第283和277行:
283: URL listFeedUrl = mWorksheet.getListFeedUrl();
277: private class UpdateBought extends AsyncTask<Void, Void, String>
logcat:
3011-3026/com.example.andb.apop_l6_google_communicator_app E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #1
Process: com.example.andb.apop_l6_google_communicator_app, PID: 3011
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.net.URL com.google.gdata.data.spreadsheet.WorksheetEntry.getListFeedUrl()' on a null object reference
at com.example.andb.apop_l6_google_communicator_app.GoogleCommunicator$UpdateBought.doInBackground(GoogleCommunicator.java:283)
at com.example.andb.apop_l6_google_communicator_app.GoogleCommunicator$UpdateBought.doInBackground(GoogleCommunicator.java:277)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
MainActivity
public class MainActivity extends ActionBarActivity implements AdapterView.OnItemClickListener{
public GoogleCommunicator mGCom = new GoogleCommunicator(this,"torprode@gmail.com");
TextView tvStatus;
EditText etAdd;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvStatus = (TextView) findViewById(R.id.tvStatus);
doSomeGoogleStuff();
buttonListener();
update();
}
private void doSomeGoogleStuff(){
mGCom.setupFeed("mandatoryProject","BuyMe");
}
private void drawListview() {
ListAdapter listAdapter = new CustomAdapter(this, mGCom.listItem, mGCom.listBought);
ListView listView = (ListView) findViewById(R.id.lv_items);
listView.setAdapter(listAdapter);
}
public void updateBought(int name, String bought) {
mGCom.updateBought(name, bought);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
}
GoogleCommunicator
public class GoogleCommunicator {
//Spreadsheet communication
private static final String mScope = "oauth2:https://www.googleapis.com/auth/userinfo.profile https://spreadsheets.google.com/feeds https://docs.google.com/feeds";
private MainActivity mActivity;
private SpreadsheetService mSpreadSheetService;
private SpreadsheetFeed mFeed;
private String mSpreadsheetName;
private String mWorksheetName;
private SpreadsheetEntry mSpreadsheet;
private WorksheetEntry mWorksheet;
private String itemName;
private int itemNameIndex;
private String itemBought;
//Constructor
public GoogleCommunicator(MainActivity activity, String email) {
mEmail = email;
mActivity = activity; //possibility for callback to method in activity class
}
//Method to be called from your application.
//Creates an instance of SetupFeedTask (an AsyncTask) and executes it
public void setupFeed(String spreadsheet_name, String worksheet_name){
mSpreadsheetName = spreadsheet_name;
mWorksheetName = worksheet_name;
new SetupFeedTask().execute();
}
public void updateBought(int name, String bought) {
itemNameIndex = name;
itemBought = bought;
new UpdateBought().execute();
}
//AsyncTask that handles network comminucation e.t.c.
private class SetupFeedTask extends AsyncTask<Void, Void, String> {
//Executes in its own "worker thread" and doesnt block the main UI thread
@Override protected String doInBackground(Void... params) {
// Do work
mToken = fetchToken();
mSpreadSheetService = new SpreadsheetService("MySpreadsheetService");
mSpreadSheetService.setAuthSubToken(mToken);
URL feed_url;
try {
feed_url = new URL("https://spreadsheets.google.com/feeds/spreadsheets/private/full");
mFeed = mSpreadSheetService.getFeed(feed_url, SpreadsheetFeed.class);
}catch(MalformedURLException e){
//TODO: handle exception
Log.v(TAG, "MalformedURLException");
return null;
}catch(ServiceException e){
//TODO: handle exception
Log.v(TAG, "ServiceException");
return null;
}catch(IOException e){
//TODO: handle exception
Log.v(TAG, "IOException");
return null;
}
try{
List<SpreadsheetEntry> spreadsheets = mFeed.getEntries();
// Iterate through all of the spreadsheets returned
for (SpreadsheetEntry spreadsheet : spreadsheets) {
if (spreadsheet.getTitle().getPlainText().equals(mSpreadsheetName)) {
List<WorksheetEntry> worksheets = spreadsheet.getWorksheets();
//Iterate through worksheets
for (WorksheetEntry worksheet : worksheets) {
if (worksheet.getTitle().getPlainText().equals(mWorksheetName)) {
mSpreadsheet = spreadsheet;
mWorksheet = worksheet;
Log.v(TAG,"Spreadsheet and Worksheet is now setup.");
}
}
}
}
}catch(ServiceException e){
//TODO: handle exception
Log.v(TAG, "Service Exception");
return null;
}catch(IOException e){
//TODO: handle exception
Log.v(TAG, "IO Exception");
return null;
}
//Just for the example.. mToken not important to return
return mToken;
}
//Call back that is called when doInBackground has finished.
//Executes in main UI thread
@Override protected void onPostExecute(String result) {
//TODO: Notify rest of application, e.g.:
// * Send broadcast
// * Send message to a handler
// * Call method on Activity
}
//Helper method
private String fetchToken(){
try {
return GoogleAuthUtil.getToken(mActivity, mEmail, mScope);
} catch (UserRecoverableAuthException userRecoverableException) {
// GooglePlayServices.apk is either old, disabled, or not present, which is
// recoverable, so we need to show the user some UI through the activity.
//TODO:
if(mActivity instanceof MainActivity){
((MainActivity)mActivity).handleException(userRecoverableException);
if(D) Log.e(TAG,"UserRecoverableAuthException");
}
} catch (GoogleAuthException fatalException) {
//TODO:
//onError("Unrecoverable error " + fatalException.getMessage(), fatalException);
if(D) Log.e(TAG,"GoogleAuthException");
} catch (IOException ioException){
if(D) Log.e(TAG,"IOException");
}
return null;
}
}
private class UpdateBought extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
try {
URL listFeedUrl = mWorksheet.getListFeedUrl();
ListFeed listFeed = mSpreadSheetService.getFeed(listFeedUrl, ListFeed.class);
ListEntry row = listFeed.getEntries().get(itemNameIndex);
row.getCustomElements().setValueLocal("bought", itemBought);
row.update();
} catch (IOException e) {
e.printStackTrace();
} catch (ServiceException e) {
e.printStackTrace();
}
return null;
}
}
}
CustomAdapter
class CustomAdapter extends ArrayAdapter<String> {
ArrayList boughtList;
MainActivity mActivity = new MainActivity();
CustomAdapter(Context context, ArrayList<String> item, ArrayList<String> bought) {
super(context, R.layout.custom_listview, item);
boughtList = bought;
}
@Override
public View getView(final int position, View convertView, final ViewGroup parent) {
LayoutInflater listViewInflater = (LayoutInflater.from(getContext()));
final View customView = listViewInflater.inflate(R.layout.custom_listview, parent, false);
final String foodItem = getItem(position);
TextView foodText = (TextView) customView.findViewById(R.id.tv_Item);
final CheckBox checkBox = (CheckBox) customView.findViewById(R.id.cb_checked);
foodText.setText(foodItem);
String foodBought = String.valueOf(boughtList.get(position));
int foodBoughtInt = Integer.parseInt(foodBought);
if (foodBoughtInt == 1) {
checkBox.setChecked(true);
} else {
checkBox.setChecked(false);
}
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (checkBox.isChecked()) {
System.out.println("Jep");
mActivity.updateBought(position, "1");
} else {
System.out.println("Nope");
mActivity.updateBought(position, "0");
}
}
});
return customView;
}
}
答案 0 :(得分:1)
您遇到了竞争条件。您必须执行异步任务,第二个异步任务取决于要使其正常工作的第一个任务。因为这两个任务都是异步完成的,所以它们在后台完成,在不同的线程上完成。您的setupFeed
方法尚未完成,然后您在新主题上启动updateBought
方法。当mWorksheet仍然为空时,updateBought
开始会发生什么。您必须重新组织代码逻辑以避免此竞争条件。在我有两个异步任务时,我过去所做的是将第二个异步任务放在第一个异步任务的onPostExecute()
中,因为onPostExecute
只在doInBackground
完成后才会出现。 / p>
Here is an execellent article on AsyncTasks and Threads from the developer guides.