EzDev.org

android-architecture

android-architecture - A collection of samples to discuss and showcase different architectural tools and patterns for Android apps.


What is difference between MediatorLiveData and MutableLiveData in in MVVM

I have searched a lot but not found the crystal clear answer for the questions:

  1. What is the difference between MediatorLiveData and MutableLiveData?

  2. What are the suitable condition to use either of them.


Source: (StackOverflow)

How does the Model(MVP in android) have access to read and modify common application data?

As I understood in the View need to create a Presenter and in the Presenter need to create Model. How does the Model(MVP in android) have access to read and modify common application data?

  • use static methods and variables to work with shared data?
  • to pass the reference to the data through View and Present in Model?
  • to create a Model not in Presenter?

Source: (StackOverflow)

A dependent feature was defined but no package ID was set. You are probably missing a feature dependency in the base feature.

I am following [google codelabs for instant app][1] And I was trying to create topeka-ui (An UI feature module for instant app).

When I try to run one of the instant app module it says :

 A dependent feature was defined but no package ID was set. You are probably missing a feature dependency in the base feature.

Source: (StackOverflow)

Currently, data binding does not work for non-base feature modules. Please, move data binding code to the base feature module

I am following Google Codelabs for instant app, and I was trying to create topeka-ui (An UI feature module for instant app).

It tells me to enable data binding like this for that UI module:

instruction for data binding

When I try to enable data binding inside the android block I get the following Error during gradle build.

Error:Currently, data binding does not work for non-base feature modules.
Please, move data binding code to the base feature module.
See https://issuetracker.google.com/63814741 for details

How can I fix it?


Source: (StackOverflow)

Confuse on dealing with relations between objects using Android Room

When using the android data-persistent library Android Room ,how can I directly insert the Comment Object into the database including all the field value, and how can I query all the value out as a Comment Object?

As I know, I can not use the Comment Object as a Entity in Room directory, because of the field replyComment is also a Comment Object. And I can not query out a Comment Object even I define a POJO using the @Relations annotation either because of the one-to-one relations and one-to-many relations all included in the Comment Object.

Is there any other way except changing the Comment Model definition, such as using foreign key, making a effect on insert action and query action?

public class Comment { 
    public String content;
    public String id;
    public Comment replyComment;
    public User user;
    public List<ImageMedia> images;
}

public class User{
    public String id;
    public String name;
}

public class ImageMedia{
    public String key;
    public String url;
}

Source: (StackOverflow)

Implementing MVP on a single activity with two (or multiple) fragments

I'm developing a small application that shows a list, and when an item is clicked it opens a secondary screen with the item details. I want to implement MVP as my architecture for this app, and i have been strugling figuring out how to do that when I have a single activity with 2 fragments.

My thought was having one presenter per fragment, which means the activity will have both presenters instances since the activity needs to instantiate them (at least that what i've seen on google's example projects from this link https://github.com/googlesamples/android-architecture)...

Then some questions came up as when an item from the list is clicked, a callback is sent to the first presenter, but at this point, who is in charge of opening the second fragment? do the presenters talk to each other? should i do it through the activity? a bit lost..

Been looking around for examples of single activity with multiple fragments implementing MVP, but couldn't find something like that.

(Yes, it can be done otherwise, but the purpose of the app is to learn implementing MVP on a single activity with multiple fragments)

Appreciate any help! Thanks!


Source: (StackOverflow)

Espresso - Difference between not(isDisplayed()) vs doesNotExist()

I was reading a todoapp from Android architectural blueprints when I came across these two tests. I cant seem to understand that why is it necessary to use doesNotExist() in createTwoTasks_deleteOneTask(), to check that an item with the specified title is deleted, when it is totally okay to use not(isDisplayed()) in createOneTask_deleteTask() for checking the same thing?

@Test
public void createOneTask_deleteTask() {
    viewAllTasks();

    // Add active task
    createTask(TITLE1, DESCRIPTION);

    // Open it in details view
    onView(withText(TITLE1)).perform(click());

    // Click delete task in menu
    onView(withId(R.id.menu_delete)).perform(click());

    // Verify it was deleted
    viewAllTasks();
    onView(withText(TITLE1)).check(matches(not(isDisplayed())));
}

@Test
public void createTwoTasks_deleteOneTask() {
    // Add 2 active tasks
    createTask(TITLE1, DESCRIPTION);
    createTask(TITLE2, DESCRIPTION);

    // Open the second task in details view
    onView(withText(TITLE2)).perform(click());

    // Click delete task in menu
    onView(withId(R.id.menu_delete)).perform(click());

    // Verify only one task was deleted
    viewAllTasks();
    onView(withText(TITLE1)).check(matches(isDisplayed()));
    onView(withText(TITLE2)).check(doesNotExist());
}

I am new in Espresso testing but I know that usually doesNotExist() is called to confirm that a view is Gone but then why not(isDisplayed()) is working fine even when the view has been removed? I tried to use doesNotExist() but it throws a error.

android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: View is present in the hierarchy: AppCompatTextView{id=2131624010, res-name=title, visibility=VISIBLE, width=1120, height=107, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=256.0, y=74.0, text=TITLE1, input-type=0, ime-target=false, has-links=false}
Expected: is <false>
Got: <true>

at dalvik.system.VMStack.getThreadStackTrace(Native Method)
at java.lang.Thread.getStackTrace(Thread.java:580)
at android.support.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:92)
at android.support.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:56)
at android.support.test.espresso.ViewInteraction.runSynchronouslyOnUiThread(ViewInteraction.java:184)
at android.support.test.espresso.ViewInteraction.check(ViewInteraction.java:158)
at com.example.android.architecture.blueprints.todoapp.tasks.TasksScreenTest.createOneTask_deleteTask(TasksScreenTest.java:284)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55)
at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:270)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1959)
Caused by: junit.framework.AssertionFailedError: View is present in the hierarchy: AppCompatTextView{id=2131624010, res-name=title, visibility=VISIBLE, width=1120, height=107, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=false, is-enabled=true, is-focused=false, is-focusable=false, is-layout-requested=false, is-selected=false, root-is-layout-requested=false, has-input-connection=false, x=256.0, y=74.0, text=TITLE1, input-type=0, ime-target=false, has-links=false}
Expected: is <false>
Got: <true>

at android.support.test.espresso.matcher.ViewMatchers.assertThat(ViewMatchers.java:1053)
at android.support.test.espresso.assertion.ViewAssertions$1.check(ViewAssertions.java:62)
at android.support.test.espresso.ViewInteraction$2.run(ViewInteraction.java:170)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:423)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7224)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Source: (StackOverflow)

Why Activity does not provide onActivityResult(...) callback as it does for permissions (onRequestPermissionsResult)?

Intro

I am writing class that provides me current localization only once if its able to, and returns default coordinats if can not do it for any reason. Class will be used in many places so I wanted to make it as simple to implement for others as it can be. So code would look like

LocationFinder locationFinder = new LocationFinder(this);
locationFinder.setLocationResolvedCallback(new LocationFinder.LocationResolvedCallback() {
        @Override
        public void onLocationFound(double latitude, double longitude) {
            Log.e("Activity", latitude + " " + longitude);
        }
    });
locationFinder.findCurrentLocation();

but there is a case when locations settings are turned off, and I have to request user to turn them on.

task.addOnFailureListener(activity, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
            int statusCode = ((ApiException) e).getStatusCode();
            switch (statusCode) {
                case CommonStatusCodes.RESOLUTION_REQUIRED:
                    try {
                        // Show the dialog and check result
                        ResolvableApiException resolvable = (ResolvableApiException) e;
                        resolvable.startResolutionForResult(activity, REQUEST_LOCATION_SETTINGS);
                    } catch (IntentSender.SendIntentException sendEx) {}
                    break;
                case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                    break;
            }
        }
    });

So now I have to go into activity and @Override onActivityResult(), handle it from activity level which makes my class less independent.

I wrote method that handle result code within my LocationFinder

 public void onActivityResult(int requestCode, int resultCode) {
    if (REQUEST_LOCATION_SETTINGS == requestCode) {
        if (resultCode == Activity.RESULT_OK) {
            requestCurrentLocation();
        } else {
            locationResolvedCallback.onLocationFound(DEFAULT_LAT, DEFAULT_LONG);
        }
    }
}

but I still have to @Override any activity that uses this class and call this method from it.

So my question is.

Why does android architects did not provide onActivityResult(...) callback as they did in case of permissions? So i could handle any request from within a class by just having reference to activity like

activity.onActivityResultCallback(...){///code}

There must be a reason but I may be missing something very obvious.


Source: (StackOverflow)