Question

I have a MainActivity.class on which I do setContentView, here are the three variables I used to

    EditText labelText = (EditText) findViewById(R.id.label_field);
    EditText phoneText = (EditText) findViewById(R.id.phone_field);
    Spinner deviceTypeSpinner = (Spinner) findViewById(R.id.device_type_spinner);
    Button registerButton = (Button) findViewById(R.id.register_button)

Now, I have a separate class which extends an async task, I am trying to modify the above fields from the async task(class located in another file).

In order to do this, I am passing the context of the activity to async task and doing the steps below

            MainActivity activity = (MainActivity)context;
            Button buttonRegister =(Button)activity.findViewById(R.id.register_button);
            EditText labelText = (EditText)activity.findViewById(R.id.label_field);

            buttonRegister.setEnabled(true);
            labelText.setFocusable(true);

but the buttonRegister returns null and the app crashes, can anybody tell me where have I gone wrong,

  java.lang.NullPointerException
    at        com.yantranet.minixagent.requests.DeviceCreateRequest$1.onClick(DeviceCreateRequest.java:237)
    at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:167)
    at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:137)
    at android.app.ActivityThread.main(ActivityThread.java:4895)
    at java.lang.reflect.Method.invokeNative(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:511)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:994)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:761)
    at dalvik.system.NativeStart.main(Native Method)
Was it helpful?

Solution

but the buttonRegister returns null and the app crashes, can anybody tell me where have I gone wrong,

i don't see where you are calling

setContentView(<layout>);

method. Without it, it always returns NPE because this method cares about inicialisation of all UI instances in specified layout. You have to call it always before you want to initialise widgets with

findViewById(<id>);

Since you are calling it in another class it won't work (class know nothing about what you did in other class). You need to:

  • pass widgets via some constructor
  • change application logic (most likely is not designated correctly)

OTHER TIPS

If you are passing the correct activity context then it should work, But I would prefer not to pass context to another class as it has nothing to with activity. You can use the following design.

  1. Register a listener with async class
  2. Implement that listener in activity
  3. Once async task completes it's work it will invoke that listener
  4. Activity will change the UI whatever it want upon listener execution.

It is not a good way to do, But if you want to access the widgets of other activity then you should make getter setter for it.

//In you mainActivity
public Button getRegisterButton()
{
     //Return register button here.
     return btn;
}
public EditText getFieldEditText()
{
      //Return editText here;
      return eText;
}

Code where you want this view.

//In Current Activity.

            MainActivity activity = (MainActivity)context;
            Button buttonRegister =activity.getRegisterButton();
            EditText labelText = activity.getFieldEditText();
         if(buttonRegister != null)
         {
            buttonRegister.setEnabled(true);
         }
         if(labelText != null)
         {
            labelText.setFocusable(true);
         }

Hope that this will helpful.

You cannot modify layout elements inside doInBackgroud().

class MyAsync extends AsyncTask<String, Integer, String>{

@Override
protected void onPreExecute() {
    // TODO Auto-generated method stub
    super.onPreExecute();
}
@Override
protected String doInBackground(String... params) {
    // TODO Auto-generated method stub
    return null;
}
@Override
protected void onPostExecute(String result) {
    // TODO Auto-generated method stub
    super.onPostExecute(result);
}

}

You can use onPreExecute() and onPostExecute(String result) to modify layout elements.

Now, I suggest you to override onPostExecute() in the same class where you call AsyncClass execute. ex:-

new MyLoadAsync(Inbox.this){
            private ProgressDialog pDialog;
            @Override
            protected void onPreExecute() {
                pDialog = new ProgressDialog(Inbox.this);//////////
                pDialog.setMessage("Loading... Please wait...");
                pDialog.setIndeterminate(false);
                pDialog.setCancelable(false);
                pDialog.show();
                super.onPreExecute();
            }
            @Override
            protected void onPostExecute(JSONArray result) {
                pDialog.dismiss();
                if(result!=null){

                }
                super.onPostExecute(result);
            }


        }.execute("your_param");

So, here you can access your layout params .

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top