Calling a method from another class is causing app to crash - android

I decided to try and make my code more object oriented and avoid repetitive code in another class.
Source code for Activities :
public class EasyMode extends MainActivity {
GameActivityPVP game = new GameActivityPVP();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
game.initializeButtons();
}
}
public class GameActivityPVP extends MainActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
initializeButtons();
}
public void initializeButtons() {
button[0] = (Button) findViewById(R.id.button1);
}
}
The second the program gets to the line where I try to call a method using game.methodName(); the program crashes. No compiling errors or anything.
I am new to programming in general so please take it easy on me and I tried to simplify my code as much as possible.
Android Monitor/logcat :
W/OpenGLRenderer: Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without...
and
W/art: Before Android 4.1, method int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView

You can use another class's method by creating object of parent class.
See below example;
Here you want to use method from 'GameActivityPVP' class. So you need to create one object in this class only.
public class GameActivityPVP extends MainActivity {
public static GameActivityPVP mGameActivity;
public GameActivityPVP getInstance(){
return mGameActivity; // assign value in onCreate() method.
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
mGameActivity = this; // Do not forget this, otherwise you'll get Exception here.
initializeButtons();
}
public void initializeButtons() {
button[0] = (Button) findViewById(R.id.button1);
}
}
Now use this Object in another class 'EasyMode' like this;
if(GameActivityPVP.getInstance()!=null){
GameActivityPVP.getInstance().initializeButtons();
}

Try This:
Make one Class Utils:
In Utils:
public class Utils{
private Activity context;
Button button;
public Utils(Activity context) {
this.context=context;
}
public void inititializeButton(Activity context){
button[0]= (Button) context.findViewById(R.id.button_flasher);
}
}
And in your Class use:
public class EasyMode extends MainActivity {
Utils utils;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
utils=new Utils(this);
utils.initializeButtons();
}
}

As already stated, you shouldn't use nested activities, they are not supposed to interact like this. If you want two activities to interact you have to do it through an intent. Regarding the duplicated code, you have few solution presented but my personal opinion is that the OOP rules are not followed. If I had to write that logic, I would create a BaseActivity to hold the common logic of the other two activities and use inheritance to extend them.
public class BaseActivity extends Activity {
protected List<Button> buttons = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_layout_pvp);
initializeButtons();
}
protected void initializeButtons() {
buttons.add((Button) findViewById(R.id.button1));
}
}
public class EasyMode extends BaseActivity {
// Add here logic that is used only in EasyMode activity
}
public class GameActivityPVP extends BaseActivity {
// Add here logic that is used only in GameActivityPVP activity
}
Note that in this way you don't have to override onCreate again to initialise the buttons and so on. Also, I saw that you used the same layout for both activities, but if you want to use different layouts you can do it as usual and then call initializeButtons.

Related

Put common listeners inside MainActivity class

Im interested if i can to set some common listeners inside main activity class? For my project i use FirebaseAuth, so i would like to init it in MainActivity onCreate(), setup needed listeners in onStart() and onStop(), and then inherit that class in every other activity class.
Some code to please you :]
MainActivity class [parent]:
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
protected FirebaseAuthentication firebaseAuthentication;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
firebaseAuthentication = new FirebaseAuthentication(FirebaseAuth.getInstance(), FirebaseDatabase.getInstance());
}
#Override
protected void onStart() {
super.onStart();
firebaseAuthentication.addAuthStateListener();
}
#Override
public void onStop() {
super.onStop();
firebaseAuthentication.removeAuthStateListener();
}
}
AuthActivity class [child]:
public class AuthActivity extends MainActivity implements FirebaseAuthentication.OnUserAuthListener {
#BindView(R.id.viewPager) LockableViewPager viewPager;
private String userUID;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_market);
ButterKnife.bind(this);
firebaseAuthentication.setOnUserAuthListener(this);
firebaseAuthentication.isSingedIn(); // check if user is singed in
}
#Override
// response for firebaseAuthentication.isSingedIn() above
public void onAuthSuccess(String userUID) {
this.userUID = userUID;
}
#Override
// response for firebaseAuthentication.isSingedIn() above
public void onAuthFailure(String message) {
snackbar(message);
Intent intent = new Intent(this, AuthActivity.class);
startActivity(intent);
finish(); // TODO mb should to delete it
}
}
Can this implementations bring me errors (maybe NullPointerExeption or what unexpectedly in future)?
Would be great if you provide me some sources to read/watch.
Thank you.
Perfect example of abstraction, but not really a question.
You will not get any nullpointers or other errors by implementing it like this.

How can I call a method of an activity in another activity which not using static references?

Maybe this question is duplicate but the answers used static references to archive this. I know that static variables can cause memory leak so we should avoid using them.
How can I do that without using static method or references?
public class FirstActivity extends Activity
{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
}
// Utility.method() used somewhere in FirstActivity
}
public class Utility {
public static void method()
{
}
}
public class SecondActivity extends Activity
{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
Utility.method();
}
}

Defining Interface inside activity

In my android application inside activity I am defining one interface like this :
public interface sideFilterInterface
{
public void changeFilters(int layoutId);
}
inside activity I use this interface like this
#Override
public void onCreate(Bundle savedInstanceState) {
mCallback = (sideFilterInterface) this;
mCallback.changeFilters(R.layout.filter_details);
}
I am implementing this interface in another fragment. when i tried this code it gives me error regarding casting here mCallback = (sideFilterInterface) this;
How to do this. Am I doing something wrong. Need help. Thank you.
The main thing is you are trying to cast your Activity into Listener if you are not implementing the Listener in your activity.
If you are calling the public void changeFilters(int layoutId) through the interface , the code will not execute as the method in the interface is abstract.You need to implement the listener in the activity and then do the code there . Something like :
public class YourActivity extends Activity implements sideFilterInterface{
#Override
public void onCreate(Bundle savedInstanceState) {
//some code
this.changeFilters(R.layout.filter_details);
}
#Override
public void changeFilters(int layoutId) {
//Implement here
}
}

Best practice: subclass or send intent?

I have two activities almost doing the same thing. The only thing that differs them is a URL to be parsed.
What is considered best practice regarding Android development, subclass just to set the URL or send the URL via an intent?
public SuperActivity extends Activity{
protected String pageUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
[...lots of stuff...]
super.onCreate(savedInstanceState);
}
}
public SubActivityOne extends SuperActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
pageUrl = "http://urlOne.com"
super.onCreate(savedInstanceState);
}
}
public SubActivityTwo extends SuperActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
pageUrl = "http://urlTwo.com"
super.onCreate(savedInstanceState);
}
}
or
public SuperActivity extends Activity{
private String pageUrl;
#Override
protected void onCreate(Bundle savedInstanceState) {
Bundle extras = getIntent().getExtras();
pageUrl = extras.getString("intent_key_url");
[...lots of stuff...]
super.onCreate(savedInstanceState);
}
}
if you have multiple activities, which share similar functionality (and/or variables/methods) -> go for sub-classing.
if all you need is to pass a value from the invoking activity, use intents (or maybe Static)
In your case, I would subclass, but do it slightly differently than you. It's dangerous to put some code in onCreate when it's not definitely needed. (You may get lost in your hierarchy and not call exactly what you want to call in the correct order) I would use an overriden method rather than a variable. Do that:
public abstract SuperActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
[...lots of stuff...]
// instead of using pageUrl, use a method when you need it: pageUrl()
super.onCreate(savedInstanceState);
}
protected abstract String pageUrl();
}
And your subactivities would look like: (only one shown here)
public SubActivityOne extends SuperActivity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected String pageUrl() {
return "http://urlOne.com";
}
}
The intent way is good too, but it might become complicated if later on you want to add more differences in your subactivities. With subclasses, it's very flexible.
To avoid duplicate code (which is mostly the good thing), make base activity class (make it abstract) and put your common code there. Then make your "real" activities extend base class. So option "A" is the way.
A third option would be to make a callback interface and have any class you want implement it. Something like "PageUrlProvider"
public interface PageUrlProvider
{
String getPageURL();
}
Then the concrete implementation would be
public MyActivity extends Activity implements PageUrlProvider
{
private String pageUrl ="http://example.com/";
#Override
protected void onCreate(Bundle savedInstanceState)
{
String myURL = getPageURL();
super.onCreate(savedInstanceState);
}
#Override
public String getPageURL()
{
return pageUrl;
}
}
Which option you choose is largely dependent on what you are trying to accomplish. But this option offers a lot of flexibility.

How should onClick Listener by defined and instantiated for an Activity

My Activity has multiple lists so I have defined MyClickListener as below:
My question is how I should instantiate this class:
MyClickListener mMyClickListener = new MyClickListener();
Or maybe it is better to instantiate inside the onCreate(Bundle) and just define above. Whats considered the better way? I don't want too much in onCreate() its already full of stuff. Any thoughts on the declaration and instatiation? Whats the best way?
private class MyClickListener implements OnClickListener
{
#Override
public void onClick(View view) {
}
}
I use same kind of class mechanism as you mentioned in the question.
this is the way i use,
public class myActivity extends Activity
{
private MyListener listener = null;
private Button cmdButton = null;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
cmdButton = (Button) findViewById(R.id.cmdButton);
cmdButton.setOnClickListener(getListener());
}
// method to fetch the listener object
private MyListener getListener()
{
if (listener == null)
{
listener = new MyListener();
}
return listener;
}
private class MyListener implements Button.OnClickListener
{
public void onClick(View v)
{
}
}
}
Why are you instantiating a listener like that in the first place? Just create a new one when you assign it to your listView.
listView.setOnClickListener( new MyListener());

Categories

Resources