In order to simplify some code, I'm wondering if it is possible to parameterize code that launches activities in an android application, so that instead of having 5
public void showSettings(View view) {
Intent SettingsActivity = new Intent(MainActivity.this, Settings.class);
startActivity(SettingsActivity);
I can do something like the following
public void showActivity(View view, String ActivityName) {
Intent ActivityName = new Intent(MainActivity.this, ActivityName.class);
startActivity(ActivityName);
Then, for each button in the UI, I simply apply the following to the "onclick" event
showActivity(Settings);
or
showActivity(domains);
This would save about 40-50 lines of code in my app. Obviously I know the above code is incorrect, but I'm not sure if it's possible to do what I'm trying to accomplish.
How about something like:
public <T> void showActivity(View view, Class<T> activity) {
Intent activityName = new Intent(MainActivity.this, activity);
startActivity(activityName);
}
You can invoke it with
showActivity(Settings.class);
I'd recommend use ACTIONs (String) instead of specifying exactly context and class. This way you even can share activities among applications, and if you decide to switch to different activity class, you can edit only android manifest, instead of editing all java source code calls this activity.
Related
I am creating an abstract base class to keep my navigation drawer code in one place and want to implement an onClickListener on my app title (defined in the toolbar) to start my launch activity
I am using the following code :
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.toolbar_title:
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
return;
}
}
The app works properly, but I read somewhere that one must not use the Application context to start new activities. However, android studio doesn't let me use any other context apart from getApplicationContext and getBaseContext, maybe because this class is abstract.
Which context should I use then?
Have a look at Context.getApplicationContext() and ContextWrapper.getBaseContext(). Both have in common to be defined on a context instance. In your case it's even an Activity.
So you could even use this as a context to start your MainActivity. This is even better, because with any other context type you' have to include the flag FLAG_ACTIVITY_NEW_TASK to start a new activity.
If you get errors by using this for a context, it's because you define your OnClickListener as anonymous inner class which of course isn't a context. For that you'd have to write MyBaseActivity.this instead. This references the outer class instance.
Well, one of the ways can be: You can define an abstract method in your BaseActivity class:
abstract void launchMainActivity();
And call this method in your click listener:
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.toolbar_title:
launchMainActivity();
return;
}
}
The sub-classes can then implement this method as:
#Override
void launchMainActivity() {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
}
how can I call MyActivitiy.this, but put arguments to it or to its Bundle?
My Code:
OnSwipeTouchListener onSwipeTouchListener = new OnSwipeTouchListener(MyActivitiy.this) {
#Override
public void onSwipeLeft() {
//your actions
}
};
The question doesn't seem to be very clear. But, consider declaring a Context ( set it equal to MyActivity.this) and using that as the parameter for your OnSwipeListener.
The way to communicate with an Activity is via Intents. In whatever code you use to start your Activity, go:
Intent intent = new Intent(someContext, MyActivity.class);
intent.putExtra("myKey", "whateverValue");
In your Activity's onCreate() method, use:
Intent intent = getIntent();
String message intent.getStringExtra("myKey", "aDefaultValueJustInCase");
Once that Activity is started, the String message will acquire the value "whateverValue".
As to using its Bundle, you probably only want to do that to recreate your Activity (say you're returning from another Activity, or pressed Back). Documentation for that is here.
Hope that answered your question. If not, please provide us more details and we will probably be able to provide more specific answers.
Let's assume that we have Activity and we want to provide Up Navigation.
When we want to start this Activity we fire simple method:
public static void startActivity(Context context) {
Intent productIntent = new Intent(context, CustomActivity.class);
productIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(productIntent);
}
The problem is that we want to start it from different Activities, and it's hard to define it parent Activity. So in that case is it necessary to add in AndroidManifest.xml attribute parentActivityName ?
I have successfully used androidannotations #Extra to decode an intent and get the sent message as this snippet demonstrates:
#Extra(MyActivity.MESSAGE)
String intentMessage;
#ViewById(displayMessage)
TextView textView;
#AfterViews
protected void init() {
textView.setText(intentMessage);
}
I'm missing how, if possible, to create the intent in the first place using annotations. e.g replace the following
Intent intent = new Intent(this,DisplayMessageActivity_.class);
intent.putExtra(MESSAGE, s);
startActivity(intent);
with something. Is this possible? (I'm totally new to all this so probably am missing something terribly obvious)
SOLUTION:
DisplayMessageActivity_.intent(this).intentMessage(s).start();
Where intentMessage is the name of the extra field.
Yes, you can use the following:
// Starting the activity
MyListActivity_.intent(context).start();
// Building an intent from the activity
Intent intent = MyListActivity_.intent(context).get();
// You can provide flags
MyListActivity_.intent(context).flags(FLAG_ACTIVITY_CLEAR_TOP).start();
// You can even provide extras defined with #Extra in the activity
MyListActivity_.intent(context).myDateExtra(someDate).start();
// startActivityForResult() equivalent:
MyListActivity_.intent(context).startForResult();
Source: https://github.com/excilys/androidannotations/wiki/HowItWorks
Solution. Finally saw the pattern on how it works. Thanks.
DisplayMessageActivity_.intent(this).intentMessage(s).start();
where intentMessage is the #Extra defined in the activity to be started e.g
#EActivity(R.layout.activity_display)
public class DisplayMessageActivity extends Activity {
public static final String MESSAGE = "net.richardriley.MyFirst.MESSAGE";
#Extra(MESSAGE)
String intentMessage;
#ViewById(displayMessage)
TextView textView;
#AfterViews
protected void init() {
textView.setText(intentMessage);
}
}
I know this is a late answer but I have developed a library that does exactly this. It uses annotations to generate the intent code.
Check it out in here: https://github.com/kostasdrakonakis/android_navigator
I have a beginners problem. Here is my situation:
I want to start a new activity from the main activity. The code to launch the new activity is found in a separate class file. I seem to be passing the wrong arguments and I am ending up in a nullpointerexception when trying to launch the new activity. The new activity launches fine when I place the code in the main activity class file, therefore the second activity and the manifest are fine. Here is a sample of my code:
In my main activity class where I instanciate the second class (THIS IS MY MAIN ACTIVITY. I OMITTED THE REST BECAUSE I DO NOT THINK IT IS RELATED TO THE PROBLEM):
Tester mytest = new Tester();
mytest.test(this);
In my second class file (THIS IS NOT AN ACTIVITY; IT IS A CLASS THAT IS INSTANTIATED IN THE ACTIVITY):
public class Tester extends Activity {
Intent myIntent;
public void test (Context context) {
myIntent = new Intent (Intent.ACTION_VIEW);
myIntent.setClass(context, newActivity.class);
thebutton.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
startActivity(myIntent);
}
}
):}
When I perform the click I receive a nullpointerexception at startactivity. Can anyone enlighten me on this please?I am sure that I am wrongly using the context.
Activities are started with Intents. Please read the Android Application Fundamentals first and try the Hello World app :)
I understood that you will use your separate Tester class at all cost ;) so I'm trying to adapt and help you out there.
First of all, don't let your class inherit from Activity. This won't help you, cause this calls will probably not have any valid context. Activity somehow implements the template pattern, providing you key method like onCreate(...), onPause(...) etc and is instantiated by the Android OS.
If you still want to use the class, you have to pass in the context. Probably you're aiming for some MVC/MVP pattern structure, anyway.
public class Tester {
private Context context;
public Tester(Context context){
this.context = context;
}
public void test () {
final Intent myIntent = new Intent(context, NewActivity.class);
//guess this comes from somewhere, hope through a findViewById method
thebutton.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
context.startActivity(myIntent);
}
}
)};
}
}
This would be a proposed solution from my side. A problem I still see here is on how you retrieve the button in that test() method. In order to have that work properly you have to retrieve it from some View class (with view.findViewByid(R.id.myButton)) or to create it dynamically and associate it with the view during the onCreate(...) of your Activity (probably using an Inflater).