I'm working on an application that has multiple Activities, and I'm tired of running back and forth between the Manifest and XML layout and stuff. Is there a way to have
Intent intent = new Intent(MainActivity.this, MainActivity.Settings.class);
Or something? Because I've tried it, it doesn't throw me an error, but it just force closes the application. I'm able to bundle all my classes from different .java into one, for ex.
public class MainActivity extends Activity
{
...
#Override
protected void onCreate(Bundle MainActivityState)
{
...
}
public class Settings extends ...
{
...
}
public class Register extends ...
{
...
}
public class Login extends ...
{
...
}
public class BeautifulLady extends personality ...
}
Simple. Just don't even try.
An activity loosely represents a single screen - something the user interacts with. Android is built around this concept and trying to circumvent it will lead to tears.
Stick with it. Having your classes in separate files, and having layout XML separate for each activity, will become your friend and will actually speed things up once you are familiar.
Start with the Activity life cycle document and read it several times until the penny drops. Then expand out from there.
http://developer.android.com/reference/android/app/Activity.html
Object oriented programming, with classes that take care of themselves, is a joy and regardless of which platform you choose to develop on is the way to go for the foreseeable future (old hands, no debates on OOP vs functional please ;)).
If you are going to do mobile development, then the separation of activities, classes and UI is the same concept, just done differently.
See also MVC programming and its' cousins.
http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
Good luck.
Perhaps you can define your Activity as 'Single Top', then launch your activity from herself like MainActivity.this.startActivity(new Intent(MainActivity.this, MainActivity.class). It'll then go into onNewIntent() and you will redisplay what you want to redisplay. This way you will have only one screen.
Related
Everybody recommended to follow MVP or MVVM pattern to maintain code readability and testability. Now I am having doubts. Now I am learning unit testing and I'm writing the code in a formal way. Not using any patterns. Now my question, can I test my code like the following?
My main activity:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public boolean testMethod(int value){
return value== 5?true:false;
}
}
My unit test class:
#RunWith(MockitoJUnitRunner.class)
public class ExampleUnitTest {
MainActivity mainActivity = new MainActivity();
#Test
public void testMethod(){
boolean result = mainActivity.testMethod(5);
assertEquals(true,result);
}
}
While running the test I did not receive any errors or issues. So is this the right way to test like this? Or what will happen if I follow this method? I am also starting to migrate my code to the MVP pattern, but I want to clear my doubts. Please let me know the reason why I should not follow the formal coding for unit testing.
Your simple example works because the code under test is not actually dependent on the Activity class or any UI state. Try to write a test for code that actually depends on UI state, e.g.
public boolean verifyInput() {
EditText edit = findViewById(R.id.edit1);
return edit.getText().toString().startsWith("0");
}
If you keep going down this road you will notice the following things to happen:
Your Activity class will become bigger and bigger (god object anti pattern).
Code that actually depends on UI state (your example does not) cannot be written with a simple unit test, an Android instrumentation test will be needed. I.e. tests will not be able execute on your host machine anymore, but have to be executed on device and need to set up and bring the Activity in the right state.
Instrumentation tests are usually slower and can be flaky, due to the nature of all the heavy lifting that will be needed to handle the UI actions and state. You will receive false negatives in your test runs.
Test methods will become more complex, because they have to bring the UI into the correct state to test the logic.
Now, there's a simple solution to all of this. Separate the core logic from the UI logic. Make the code that handles the UI as simple as possible and move the (complex) core logic into a separate class. Suddenly you have a 2nd class with methods that will make it easier for you to reason about and write tests for. This 2nd class will also match the actions the user of your app will be able to take.
After some time you will want to split up the 2nd class too, because you will notice that some subset of methods have nothing to do with another subset of methods. So you keep modularizing and crafting to make it easier for you as a developer to understand and to work with the code. This is the time where patterns like MVP, MVVM, ... will become handy.
Please note that I'm not recommending you to jump into using patterns like MVVM immediately. If you are just starting to learn Programming, Software Development or Android, it is totally fine to do what you do. You'll learn by experiencing these "pain points", that a lot of us have already run into, and at that time you will start to look for improvements and why others recommend to use specific patterns or best practices.
Also, take a look at what low coupling and high cohesion means and why it's important for you as a developer.
I have a situation for each i am trying to find a better (read optimized) pattern to employ.
Essentially, i have three activities - LaunchActivity, WelcomeActivity and MainActivity.
The LaunchActivity is the DEFAULT LAUNCHER activity and in my case, LaunchActivity does not show any UI i.e i don't call setContentView() at all in onCreate(). All that i am doing is, essentially, in onStart(), i check certain conditions and based on the result, either launch WelcomeActivity or MainActivity.
Now, i am wondering, should i really use an Activity [LaunchActivity's superclass] do some checks? Is there a light weight option that i could use to quicken the launch process since instantiating an Activity could be fairly time consuming and expensive?
Thanks all.
I use activity acting as a splash screen in my applications while dealing with such kind of scenarios.The benefit of doing this is that it is giving my application a nice interface, and a graphically rich promotion, and also in that splash Activity,I am taking decisions that what activity should be started next on the basis of last saved state of my Android Application.
Another alternative(which i will not implement in any application developed by me) is to start the Welcome Activity everytime,and in its onCreate() Check some condition.If that condition is met then, open the MainActivity by using intents...else carry on with the flow of the welcome Activity
public class WelcomeActivity extends Activity{
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(your condition)//check some condtion here
{
// if met,go to MainActivity
}
else
{
//carry on with the flow of WelcomeActivity
}
}
}
Overall, I believe using the first approach is better way , because it is just adding an overhead of only one activity,but making the flow of the application cleaner
So what I want to do is this. I want to have a class that contains other classes which start activities, but I'm not sure if its possible, or even a good idea. An Example:
public class General{
public class Activity1 extends Activity{
//Start Activity
}
}
Is there a way to call such an activity?
So the solution I chose to go with was to use packages. After reading about it here http://developer.android.com/guide/topics/manifest/manifest-intro.html and here Android: Including multiple Java Packages to Manifest , it seems like a better method to do what I stated above.
It is well know to people using Google Maps in an Android app that they can only use one MapActivity per process. There is a bug discussing this in detail along with the workaround of putting each MapActivity in a separate process. I don't want to do this in my app for a few reason and have developed another workaround that seems to work.
For each Activity that contains a map, I have it extend ActivityGroup and create/destroy the MapActivity in onResume/onPause as a child activity. This ensures there will only be one instance of a MapActivity at a time (assuming you have one Activity showing at a time). Below is a simplified version of my implementation:
public class MyMapActivityGroup extends ActivityGroup {
#Override
protected void onResume() {
super.onResume();
addMapView();
}
#Override
protected void onPause() {
super.onPause();
removeMapView();
}
private void addMapView() {
Intent intent = new Intent(this, MyMapActivity.class);
Window window = getLocalActivityManager().startActivity("map", intent);
setContentView(window.getDecorView());
}
private void removeMapView() {
setContentView(new FrameLayout(this));
getLocalActivityManager().removeAllActivities();
}
}
The MapActivity I am using is nothing special and doesn't require any modification. It just sets a MapView as its content view.
This seems to work fine for me. But is there any downside to doing this? My main concern is a memory leak created when going between activities containing a map.
I would guess that the only reason to not do this would be performance. The map activity can already be a bit of a dog, especially when starting it, so if you find yourself allocating and deallocating the view frequently, this might perform pretty poorly. However, its really dependent on how often the view will be created and removed, which depends entirely on behavioral aspects of your application.
I would like to run a piece of code every time any activity or service is started. In this piece of code, I might do things such as set the default uncaught exception handler and manage log levels.
The problem is that I have an activity which starts with the user clicking the application icon. I have another which starts if a certain intent is broadcasted, possibly from another app and possibly called before the user click the launch icon. Same goes for services.
I need to guarantee that a certain piece of code will be run while keeping the code clean; that is to say, without having to manually add that snippet of code to every activity and service class that I have.
Could you not extend the basic Activity class for Android like this:
public class MyClass extends Activity {
public void onCreate(Bundle bundle) {
//Add custom code here
}
}
Then have all of your actual "Activity"'s in your application extend the custom class?
public class MyInterfaceClass extends MyClass {
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
//Other code here
}
}
That way all your custom code will be called when the Activity starts up.
For an application called Wibble...
public class Wibble extends Application {
protected static void DoSomething()
{
// Do your common code here
}
}
Then extend Activity...
public class WibbleActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Wibble.DoSomething();
}
}
Then derive all activity classes from WibbleActivity...
public class Whatever extends WibbleActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// WibbleActivity calls Wibble.DoSomething()
// so the 'Whatever' class doesn't have to.
}
}
Any Activity derived from WibbleActivity will run Wibble.DoSomething() implicitly.
If you want Services in the mix I can't help - I'm an Android 'rookie' and haven't got on to Services yet but I suspect extending your own app-level Service class might work in the same way.
You could extend Application and do it in its onCreate() method.
You have two choices
A) You can manually add the code - it might be only two lines importing and instantiating something from a source file you copy in unmodified - to every separate component that you write. It will only be in your projects, not in other people's unless they do it too.
B) You can, after no small difficulty, learn to make your own custom version of android that automatically does this each time it starts up a suitable component, and install this customized version on developer phones or hacked consumer phones.
"started" is ambiguous - what are you referring to? onCreate? onResume?
In any case, your best bet is to have a separate class with a static method that does the code you are talking about, and you call that in every single onCreate (or onResume, whichever you need) of each one of your activities.
That, or you create your own Activity subclass and derive all your activites from it, and override onCreate (or onResume). All your onCreate/onResume implementations are required to call the superclass' implementation, so you're guaranteed to have your code caled.