NullPointerException:Google Spreadsheet,doInBackground

时间:2015-05-15 14:15:05

标签: android google-sheets

我得到了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;
    }
}

1 个答案:

答案 0 :(得分:1)

您遇到了竞争条件。您必须执行异步任务,第二个异步任务取决于要使其正常工作的第一个任务。因为这两个任务都是异步完成的,所以它们在后台完成,在不同的线程上完成。您的setupFeed方法尚未完成,然后您在新主题上启动updateBought方法。当mWorksheet仍然为空时,updateBought开始会发生什么。您必须重新组织代码逻辑以避免此竞争条件。在我有两个异步任务时,我过去所做的是将第二个异步任务放在第一个异步任务的onPostExecute()中,因为onPostExecute只在doInBackground完成后才会出现。 / p>

Here is an execellent article on AsyncTasks and Threads from the developer guides.