简体   繁体   中英

How to pass context to Intent in android library?

I created a library for the recurrent screen in android and when I tried to implement it in my activity I got this error message.

java.lang.NullPointerException: Attempt to invoke virtual method 'android.content.Context android.app.Activity.getApplicationContext()' on a null object reference
        at com.expert.recur.ScreenReco.<init>(ScreenReco.java:15)
        at com.expert.recurringscreen.MainActivity.onCreate(MainActivity.java:18)

My code. MainActivity.java:

public class MainActivity extends AppCompatActivity {

    ScreenReco screenReco;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        screenReco=new ScreenReco(MainActivity.this);//line 18
        screenReco.value = 1000;
        screenReco.runnable.run();

    }
}

My library:

public class ScreenReco {
    Activity activity;

    public ScreenReco(Activity activity) {
        this.activity = activity;
    }

    public Context context = activity.getApplicationContext();//line 15
    public int value;
    public Handler handler = new Handler();
    public Runnable runnable = new Runnable() {
        @Override
        public void run() {
            Intent i = new Intent(context, context.getClass());
            handler.postDelayed((Runnable) context,value);
            context.startActivity(i);
        }
    };
}
 java.lang.NullPointerException: Attempt to invoke virtual method
 'android.content.Context android.app.Activity.getApplicationContext()'
 on a null object reference

You can create a Constructor .

A constructor is a special method that is called whenever an object is created using the new keyword.

public class ScreenReco {
Activity activity;     

     ScreenReco(Activity ctx)
     {
       this.activity=ctx
     }

}

Then

ScreenReco screenReco=new ScreenReco(MainActivity.this);

Or

      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      screenReco=new ScreenReco(MainActivity.this);

You are supposed to create an object of ScreenReco class before assigning values to its variables...

public class MainActivity extends AppCompatActivity {

ScreenReco screenReco;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      screenReco=new ScreenReco(); // you are missing this
      screenReco.context = this;
      screenReco.value = 1000;
      screenReco.runnable.run();
  }

}

But I strongly recommend you to use constructors for this... it's the good practice

Your MainActivity is almost fine. But, it is not recommended to call run(); method of Runnable object ourself. Instead, pass the Runnable object in a constructor of a Thread object and call start(); method on the Thread object and let the system call the run(); method itself when it is appropriate. Your improved MainActivity may look like this:

public class MainActivity extends AppCompatActivity {

    ScreenReco screenReco;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        screenReco=new ScreenReco(MainActivity.this, 1000);//line 18
        // screenReco.value = 1000;
        // if you want to run `runnable` in a new Thread
        // new Thread(screenReco.runnable).start();

        //or if you want to run it in the same thread
        //new Handler().post(screenReco.runnable);

        //screenReco.runnable.run();

    }
}  

Now moving into your library file ie ScreenReco.java , it looks like activity variable hasn't been initialized while you are trying to call getApplicationContext() method in the class as @PraveenSP's answer has already said. A better practice would be declare all required class variable at once and then initialize them all in the class constructor as:

public class ScreenReco {
    // if you need this activity variable to just use as context
    // then do not use this variable here just use context only
    Activity activity;
    // the better practice here is to declare these variable as private 
    // and pass values for these variables in constructor and initialize them there 
    public Context context;
    public int value;
    public Handler handler;
    public Runnable runnable;

    // constructor improved from your code
    public ScreenReco(Activity activity, int value) {
        this.activity = activity;// this only if you are using activity
        // object to something otherwise get rid of this variable.
        this.context = activity.getApplicationContext();
        this.handler = new Handler();
        this.value = value;
        this.runnable = new Runnable() {
        @Override
        public void run() {
            Intent i = new Intent(context, context.getClass());
            // handler.postDelayed((Runnable)context, value); 
            context.startActivity(i);
        }
        // this is the edit you need 
        this.handler.postDelayed(runnable, value);
    };
    }

   // this version of constructor is what exactly I would have done by declaring class variable as `private` up there 
   // public ScreenReco(Context context, int value) {
        // this.activity = activity;
        // this.context = context;
        // this.handler = new Handler();
        // also initialize `value` and `runnable` object here
        // this.value = value;
        // this.runnable = new Runnable() {
        // @Override
        // public void run() {
            // Intent i = new Intent(context, context.getClass());
            // handler.postDelayed((Runnable) context,value);
            // context.startActivity(i);
        // }
    // };
    // }
}  

Also, I'm so confused by the code you wrote inside the runnable 's run() method. It looks like you are trying to start the MainActivity from MainActivity . And, in the line below, you tried to cast context variable to Runnable which is very error-prone.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM