I am making an application for android which could grow somewhat large over time. What I would like to do is implement into the main class sub files for logic. For example:
The main activity uses a surfaceview.
class Battle extends SurfaceView implements SurfaceHolder.Callback {
I want to add all logic related to touch events in a file called touchActions.java
public class touchActions extends Battle {
It appears to work fine with no errors in Eclipse. But when I try to run it on my phone, I get a null pointer exception for the following line.
if (_touch.checkHitBox(1)) {
_touch being initiated after the Battle class is declared.
public touchActions _touch;
What is the proper way to do this, or what could be causing the nullpointerexception?
EDIT:
The goal here is organization of code, so that I don't end up with one gigantic file of code. Can I make an inner class while still using a different file? If you know of a tutorial, that would be great too.
_touch being initiated after the Battle class is declared.
public touchActions _touch;
not initiated ... just declared u need to initiatie it with something like this
_touch = new touchActions();
EDIT:
if public touchActions _touch; is declared in Battle class you do it all wrong ...
it should be something like this
class Battle extends SurfaceView implements SurfaceHolder.Callback {
public touchActions _touch;
public Battle (){
_touch = new touchActions(this);
_touch.callingMethodFromTouch();
}
}
//should not extends Battle
public class touchActions {
Battle parent_;
public touchActions (Battle parent){
parent_ = parent;
}
.... rest of implemetation you can call parent_.methodFromBattleClass(); here
}
Related
I'm trying to understand concept of MvP design pattern. I mean, I get it, its quite easy. The main problem is optimal implementation. I tried to make my own BaseActivity, BasePresenter and BaseView just to extract part of a joint from all of my activities, I've done this this way:
BaseActivity
public abstract class BaseActivity<T extends BasePresenter<? extends IBaseView>> extends FragmentActivity implements IBaseView {
protected T presenter;
private ActivityConfig activityConfig;
#Override
final protected void onCreate(Bundle savedInstanceState) {
activityConfig = getConfig();
super.onCreate(savedInstanceState);
presenter = createPresenter();
setContentView();
initLibraries();
prepareView(savedInstanceState);
addFragments();
}
protected abstract ActivityConfig getConfig();
protected abstract T createPresenter();
protected abstract void prepareView(Bundle savedInstanceState);
protected abstract void addFragments();
private void setContentView(){
View root = View.inflate(this, activityConfig.layoutId, null);
setContentView(root);
}
private void initLibraries() {
ButterKnife.bind(this);
Timber.plant(new Timber.DebugTree());
}
#Override
public BaseActivity getCurrentContext() {
return this;
}
#Override
public T getPresenter() {
return presenter;
}
}
BasePresenter
public abstract class BasePresenter<T extends IBaseView> {
public abstract void loadData(boolean refresh);
}
BaseView
public interface IBaseView {
BaseActivity getCurrentContext();
BasePresenter getPresenter();
}
It works fine but I feel like this is bad designed so I want to use Mosby instead. The problem is that all of the tutorials don't touch aspect of base classes, they just use Mosby's ones as base (with is bad I suppose? couse I have to duplicate my code (Butterknife.bind() for example). So can you guys give me some good designed quickstart classes for Mosby MVP or give me some tips how should I divide my project? Thanks!
So I see two possibilities:
You could extend from Mosby's MvpActivity as your base class and add your staff like initView(), initLibraries() etc. So that BaseActivity<P extends BasePresenter<? extends BaseView>> extends MvpActivity<P> implements BaseView. Then MyFooActivity extends BaseActivity<FooPresenter>. So you include Butterknife once in BaseActivity and it should work. However, you might have to duplicate that code like Butterknife.bind()` for Fragments, as Activity and Fragments obviously don't have the same super class. I will show you how to solve that above.
Do the other way around: Integrate Mosby's functionality into your BaseActivity. Mosby is build with the principle of "favor composition over inheritance". So what does this actually mean? Mosby offers a ActivityMvpDelegate. As the name already suggests this delegate does all the work of instantiating Presenter etc. But instead of inheriting from MvpActivity you use this delegate and invoke the corresponding delegate methods. Actually Mosby's MvpActivity is doing exactly that if you have a look at the source code. So instead of extending from Mosby'sMvpActivity you simply use MvpActivityDelegate in your BaseActivity.
So what about duplicating code like Butterknife.bind() i.e. in Activity and Fragment. Well, Mosby can share his code like instantiating Presenter etc. between Activity and Fragment because both use the mosby delegate.
So you could apply the same principle: You could put the shared code into a delegate and call the delegate from both, activity and fragments.
The question is: is it worth i.e. Butterknife.bind() is just one single call. You would also have to make one single call yourDelegate.doSomething() ...
But if you have to reuse "critical code" between activity and fragments then favor composition like Mosby does.
If you know that you are only working with Activites then extending from Mosby's MvpActivity would also be a good option as described in 1. solution.
I just wanted to add to sockeqwe's first answer.
It is perfectly fine to create your own base class where it makes sense. It's also pretty straightforward.
For example, I needed to create a base Fragment with some default behavior. All you need to do is duplicate the base generic type signature and pass it along to the base class.
For example:
public abstract class MyBaseFragment<V extends MvpView, P extends MvpPresenter<V>> extends MvpFragment<V, P>
I have MainActivity that shows FragmentDialog (EditIntervalFragment) in order to capture user's input. Activity implements EditIntervalListener interface. In onAtach method fragment casts activity to EditIntervalListener.
I want to test that my EditIntervalFragment properly calls EditIntervalListener methods with correct parameters.
My initial intent was to use Roblectric and Mockito. The following code almost works.
#Test
public void shouldCallInterfaceAfterModify() {
MainActivity hostActivity = Robolectric.setupActivity(MainActivity.class);
EditIntervalFragment editIntervalFragment = EditIntervalFragment.getInstance(0, TEST_NAME, TEST_DURATION);
editIntervalFragment.show(hostActivity.getSupportFragmentManager(), "test");
AlertDialog dialog = (AlertDialog) editIntervalFragment.getDialog();
assertNotNull(dialog);
EditIntervalFragment.EditIntervalListener activity = Mockito.spy(hostActivity);
dialog.findViewById(android.R.id.button1).performClick();
verify(activity).onIntervalChanged(0,TEST_NAME,TEST_DURATION);
}
The problem with this code that it uses real MainActivity. It means that all MainActivity's logic will be executed. I want to avoid this. How can I do this?
Update
I found a way to not call real MainActivity. I created another activity, just for test.
public class ActivityTest extends FragmentActivity implements EditIntervalFragment.EditIntervalListener {
//empty methods here
}
My test now looks like this
#Test
public void shouldCallInterfaceAfterModify() {
ActivityTest hostActivity = Robolectric.setupActivity(ActivityTest.class);
ActivityTest spy = Mockito.spy(hostActivity);
EditIntervalFragment editIntervalFragment = EditIntervalFragment.getInstance(0, TEST_NAME, TEST_DURATION);
editIntervalFragment.show(spy.getSupportFragmentManager(), "test");
AlertDialog dialog = (AlertDialog) editIntervalFragment.getDialog();
assertNotNull(dialog);
dialog.findViewById(android.R.id.button1).performClick();
verify(spy).onIntervalChanged(0, TEST_NAME, TEST_DURATION);
}
But after test execution I receive error saying than only spy.getSupportFragmentManager() was called. I'm 100% sure that onIntervalChanged should be called.
Looking for help. How can I implement such kind of test?
That is always challange to make work spies when you don't control lifecycle.
What we are usually doing we extracting all not related functionality to utility classes and mock them in tests. It also helps with design of the application (Single class responsibility rule).
Of course it depends if you do something with this data. If it is just data class than I would have Factory for creating this data classes and again mock it in tests. All this requires proper DI (look to Dagger).
And there is nothing wrong with your approach but it doesn't force you to think about your app as small parts that interact with each other. But at the same time it brings more complexity which pays off later
I ended up with this solution. Create an Activity that implements interface an keep track of all interaction.
public class ActivityTest extends FragmentActivity implements EditIntervalFragment.EditIntervalListener {
public int mIntervalChangedCalls = 0;
public int mPosition;
public String mName;
public long mDurationMillSec;
#Override
public void onIntervalChanged(int position, String name, long durationMillSec) {
mIntervalChangedCalls++;
mPosition = position;
mName = name;
mDurationMillSec = durationMillSec;
}
}
My test looks like this
#Test
public void shouldCallOnIntervalChanged() {
ActivityTest hostActivity = Robolectric.setupActivity(ActivityTest.class);
EditIntervalFragment editIntervalFragment = EditIntervalFragment.getInstance(0, TEST_NAME, TEST_DURATION);
editIntervalFragment.show(hostActivity.getSupportFragmentManager(), "test");
AlertDialog dialog = (AlertDialog) editIntervalFragment.getDialog();
assertNotNull(dialog);
dialog.findViewById(android.R.id.button1).performClick();
assertThat(hostActivity.mIntervalChangedCalls).isEqualTo(1);
assertThat(hostActivity.mPosition).isEqualTo(0);
assertThat(hostActivity.mName).isEqualTo(TEST_NAME);
assertThat(hostActivity.mDurationMillSec).isEqualTo(TEST_DURATION);
}
I'm not completely happy with this creation of a separate class just for test purposes. I suppose the same can be achieved with Mockito or Robolectric, but I do not know how.
So I'm still open for any ideas or suggestions. I'll accept my own answer, if no one gives better solution in a week.
I have an android/programming design question. For some reason I feel my design is awkward but if it is correct (no issues) then I would like a confirmation so I know I am on the right path.
Often I come across where I have Activity (lets say it has map). I don't want to put everything in this class ( ie map work). I usually create the activity class and another class (say map worker). I pass the activity as a reference to the map worker class, so that map worker class can method in there. Something like that
public class MainActivity extends Activity{
public void onCreate(){
MapWorker myWorker = new MapWorker(this);
}
public renderUpdate (Marker m){
mapView.addMarker(m)
}
}
The map worker class is as follows
public class MapWorker {
MainActivity act;
public void MapWorker(MainActivity act){
this.act = act;
}
public doWork(){
//do lots of work
.
.
.
act.renderUpdate(marker)
}
}
These classes have two way linking as you see. Is this ok or should I do it differently?and Why?
Thank you so much
I'm using common code in my Activity like this:
abstract class CommonCode extends Activity {
//Common Code here...
}
then in my "Activity" I extend CommonCode instead of Activity and it all works fine.
My problem arise when I try to use commoncode in a PreferenceActivity, I tried:
abstract class CommonCode extends Activity {
class CommonCodePreferences extends PreferenceActivity {
}
//Common Code here...
}
but it isn't right.
How can I do it?
May I suggest that you prefer composition over inheritance and do something like this:
abstract class CommonCode {
Activity parent;
public CommonCode(Activity activity) {
parent = activity;
}
}
class MyActivity extends Activity {
CommonCode commonCode;
public MyActivity() {
commonCode = new CommonCode(this);
}
}
This is a little more code to write in each activity, but it has a lot of advantages:
It can also easily handle PreferenceActivity and other classes
It is easier to test and mock
I usually have one each since you can't mess with the existing hierarchy of the base classes.
For example, I have an ActivityBase, ServiceBase, ListActivityBase, etc. If you want to have common code that they all use, I would suggest using composition - each of your base classes has a single instance of your CommonCode class or something to that effect. Another possibility is to use static methods and/or use a custom Application class (requires declaring the custom Application class in the manifest in the name attribute of the application element)
I have created a service for TweetCollectorService. I want to call a method of another class in my service.can I do this Plz Help me.
Thankyou
Yes you can.. Only difference here is the method execution also occurs in background process.. No other difference..
Its not best practice to have other utility functions/methods in Activity, which mainly is to handle user interaction. so Strictly follow java convention and create different class which has all these methods, so it achieves cohesion.
You can dosomething like below..
Class YourActivity extends Activity{
public void do(){
// do your task
}
and in service just say new YourActivity().do()
}
Yes you can able to call the other class method. If you using your custom class then create the method as static so no need to create object of that class
suppose your custom class which extend Activity or not then also you can do like this way.
class CustomClass extends Activity{
public static void mymethod(){
// call me
}
}
now you can call into the service like this way without creating any object as explicitly
class MyService extends Service{
onCreate(){
CustomClass.mymethod();
}
}