Giter Site home page Giter Site logo

android / architecture-samples Goto Github PK

View Code? Open in Web Editor NEW
43.8K 2.4K 11.6K 13.02 MB

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

License: Apache License 2.0

Kotlin 100.00%
android-architecture android samples

architecture-samples's Introduction

Android Architecture Samples

These samples showcase different architectural approaches to developing Android apps. In its different branches you'll find the same app (a TODO app) implemented with small differences.

In this branch you'll find:

  • User Interface built with Jetpack Compose
  • A single-activity architecture, using Navigation Compose.
  • A presentation layer that contains a Compose screen (View) and a ViewModel per screen (or feature).
  • Reactive UIs using Flow and coroutines for asynchronous operations.
  • A data layer with a repository and two data sources (local using Room and a fake remote).
  • Two product flavors, mock and prod, to ease development and testing.
  • A collection of unit, integration and e2e tests, including "shared" tests that can be run on emulator/device.
  • Dependency injection using Hilt.

Variations

This project hosts each sample app in separate repository branches. For more information, see the README.md file in each branch.

Stable samples - Kotlin

Sample Description
main This branch
service-locator A simple setup that removes Hilt in favor of a service locator
livedata Uses LiveData instead of StateFlow as the data stream solution
usecases Adds a new domain layer that uses UseCases for business logic (not using Compose yet)
views Uses Views instead of Jetpack Compose to render UI elements on the screen
views-hilt Uses Views and Hilt instead together

Screenshots

Screenshot

Why a to-do app?

The app in this project aims to be simple enough that you can understand it quickly, but complex enough to showcase difficult design decisions and testing scenarios. For more information, see the app's specification.

What is it not?

Who is it for?

  • Intermediate developers and beginners looking for a way to structure their app in a testable and maintainable way.
  • Advanced developers looking for quick reference.

Opening a sample in Android Studio

To open one of the samples in Android Studio, begin by checking out one of the sample branches, and then open the root directory in Android Studio. The following series of steps illustrate how to open the usecases sample.

Clone the repository:

git clone [email protected]:android/architecture-samples.git

This step checks out the master branch. If you want to change to a different sample:

git checkout usecases

Note: To review a different sample, replace usecases with the name of sample you want to check out.

Finally open the architecture-samples/ directory in Android Studio.

License

Copyright 2022 Google, Inc.

Licensed to the Apache Software Foundation (ASF) under one or more contributor
license agreements. See the NOTICE file distributed with this work for
additional information regarding copyright ownership. The ASF licenses this
file to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License.

architecture-samples's People

Contributors

adazh avatar alexvanyo avatar ceruleanotter avatar curioustechizen avatar dmeng avatar dougsig avatar dturner avatar egor-n avatar flipper83 avatar florina-muntenescu avatar freewheelnat avatar grepx avatar h3r3x3 avatar jfschmakeit avatar josealcerreca avatar malmstein avatar manuelvicnt avatar nkoroste avatar oldergod avatar quangson91 avatar rainer-lang avatar richarth avatar riggaroo avatar samiuelson avatar sfuku7 avatar sharifsalah avatar slinzner avatar tomaszrykala avatar tunjid avatar zsmb13 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

architecture-samples's Issues

Sample MVVM with databinding?

I was thinking about working on an example of this over the weekend. MVVM + databinding were made for each other and it would be nice if there was an example

using addPresenter instead of setPresenter

In some case, one view need more than one presenter to accomplish business.
So I always change the code like..

View

private FirstPresenter mFirstPresenter;
private SecondPresenter mSecondPresenter;

public void addPresenter(Presenter presenter) {
    if (presenter instanceof FirstPresenter ) {
        mFirstPresenter = (FirstPresenter) presenter;
    }

    if (presenter instanceof SecondPresenter ) {
        mSecondPresenter = (SecondPresenter) presenter;
    }
}

how to deal with the view may not be able to handle UI updates anymore

when network api callback, the view may not be able to handle UI updates anymore, how to deal with and how to check?
the view holds the presenter instance, presenter holds view instance, and presenter holds data loader instance. so that when network is slow , and user close activity without data loader calling back,the activity instance will not be freed and collected . if user open and close activity with data loading frequently, in this moment, many activities in memory will not be freed, and the memory use will increase. how to deal with? and what about using SoftReference to view in presenter?

new task - backpress - not saved

  1. fab: create new task
  2. title="Test"
  3. backpress
  4. return to main-activity without asking, saving or anything else

tested with rxjava-branch

UPDATE:
Should even happen in basic-sample.

Presenter - Binding with View

The Presenter is just created and code like this in the activity looks pretty lame although meaningful work happens in the presenter constructor

Proposal:

Introduce a method bind in the Presenter.

So, the code in presenter class will be:

class ddEditTaskPresenter implements
        AddEditTaskContract.Presenter,
        TasksDataSource.GetTaskCallback {

  Presenter(...) {
    this.blah = checkNotNull(blah);
    ...
  }

  bind() {
    mAddTaskView.setPresenter(this);
  }

}

and the activity will be:

class AddEditTaskActivity {
   onCreate(...) {
      ....
      presenter = new AddEditTaskPresenter(....);
      //wherever required...
      presenter.bind();
   }
}

Thoughts?

I‘m tired about the problem

Error:(97, 37) 警告: [unchecked] 方法调用未经过检查: 将接口 View中的方法 showTasks应用到给定的类型
需要: List
找到: List

Request - Un-official sample

I wanna submit an un-official sample request.
Sample500px
I have made this sample using retrofit2, dagger, rxjava following MVP architecture provided by you guys.
Please let me know your thoughts.
Thanks to community for this project open source. 👍

NPE in todo-mvp

in TaskDetailActivity.java

Here will case NPE.

...
public class TaskDetailActivity extends AppCompatActivity {
...
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        if (taskDetailFragment == null) {
            taskDetailFragment = taskDetailFragment.newInstance(taskId);
        ...
    }
...

try

taskDetailFragment = TaskDetailFragment.newInstance(taskId);

Request - Un-official sample

I wanna submit an un official sample request.
Sample500px
I have made this sample combining dagger2, rxjava, and retrofit2
Please let me know your thoughts :)
Thanks to the community for making this project open source 👍

GetStatistics UseCase for "todo-mvp-clean"

Calculation of the statistics in StatisticsPresenter looks more like a domain logic, not a presentation.
Plus StatisticsPresenter right now have dependency on TasksFilterType, which could be avoided.
My suggestion is to create an additional UseCase: GetStatistics, which will simplify StatisticsPresenter, and make it independent from tasks and data packages.

I implemented it here, it is required some polishing, but I hope that idea is clear.

[Request] New sample with Agera

I'm not sure if this make sense, 'cause the RxJava version is already in progress and both may result in similar codes. Nevertheless, would be interested to see the differences fleshed out.

error when adding task

I'm testing the app and getting an arror when adding a task

my phone is galaxy s3
android: 5.0.1
android studio 2.2 preview
gradle: 2.2.alpha

E/AndroidRuntime: FATAL EXCEPTION: main
                  Process: com.example.android.architecture.blueprints.todomvpdagger.mock, PID: 8462
                  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.android.architecture.blueprints.todomvpdagger.mock/com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskActivity}: android.view.InflateException: Binary XML file line #30: Error inflating class EditText
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2702)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767)
                      at android.app.ActivityThread.access$900(ActivityThread.java:177)
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449)
                      at android.os.Handler.dispatchMessage(Handler.java:102)
                      at android.os.Looper.loop(Looper.java:145)
                      at android.app.ActivityThread.main(ActivityThread.java:5951)
                      at java.lang.reflect.Method.invoke(Native Method)
                      at java.lang.reflect.Method.invoke(Method.java:372)
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400)
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195)
                   Caused by: android.view.InflateException: Binary XML file line #30: Error inflating class EditText
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:770)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
                      at com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskFragment.onCreateView(AddEditTaskFragment.java:99)
                      at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252)
                      at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742)
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617)
                      at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339)
                      at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:601)
                      at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1234)
                      at android.app.Activity.performStart(Activity.java:6329)
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767) 
                      at android.app.ActivityThread.access$900(ActivityThread.java:177) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:145) 
                      at android.app.ActivityThread.main(ActivityThread.java:5951) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:372) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 
                   Caused by: android.content.res.Resources$NotFoundException: File res/drawable-v21/abc_edit_text_material.xml from drawable resource ID #0x7f020015
                      at android.content.res.Resources.loadDrawableForCookie(Resources.java:3735)
                      at android.content.res.Resources.loadDrawable(Resources.java:3603)
                      at android.content.res.TypedArray.getDrawable(TypedArray.java:762)
                      at android.view.View.<init>(View.java:3957)
                      at android.widget.TextView.<init>(TextView.java:998)
                      at android.widget.EditText.<init>(EditText.java:74)
                      at android.widget.EditText.<init>(EditText.java:70)
                      at android.support.v7.widget.AppCompatEditText.<init>(AppCompatEditText.java:60)
                      at android.support.v7.widget.AppCompatEditText.<init>(AppCompatEditText.java:56)
                      at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:112)
                      at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:980)
                      at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1039)
                      at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
                      at android.view.LayoutInflater$FactoryMerger.onCreateView(LayoutInflater.java:181)
                      at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:732)
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:813) 
                      at android.view.LayoutInflater.rInflate(LayoutInflater.java:821) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:511) 
                      at android.view.LayoutInflater.inflate(LayoutInflater.java:415) 
                      at com.example.android.architecture.blueprints.todoapp.addedittask.AddEditTaskFragment.onCreateView(AddEditTaskFragment.java:99) 
                      at android.support.v4.app.Fragment.performCreateView(Fragment.java:1974) 
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067) 
                      at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1252) 
                      at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:742) 
                      at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1617) 
                      at android.support.v4.app.FragmentController.execPendingActions(FragmentController.java:339) 
                      at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:601) 
                      at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1234) 
                      at android.app.Activity.performStart(Activity.java:6329) 
                      at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665) 
                      at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2767) 
                      at android.app.ActivityThread.access$900(ActivityThread.java:177) 
                      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1449) 
                      at android.os.Handler.dispatchMessage(Handler.java:102) 
                      at android.os.Looper.loop(Looper.java:145) 
                      at android.app.ActivityThread.main(ActivityThread.java:5951) 
                      at java.lang.reflect.Method.invoke(Native Method) 
                      at java.lang.reflect.Method.invoke(Method.java:372) 
                      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1400) 
                      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1195) 
                   Caused by: org.xmlpull.v1.XmlPullParserException: Binary XML file line #24: <nine-patch> requires a valid 9-patch source image
                      at android.graphics.drawable.NinePatchDrawable.updateStateFromTypedArray(NinePatchDrawable.java:445)
                    at android.graphics.draw

how to run unittest and uitest ?

I download the android-architecture-todo-mvp-loaders program,and then i run TaskScreenTest.java,but i got wrong ,the follow is the message.i don't know how to do ?i want do unit test and ui test for a program ?Thank you very much!
d

on todo-mvp, move logic from view to presenter

In AddEditTaskFragment, the logic to decide whether to update task or create a new task is made and presenter method is called accordingly.

fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (isNewTask()) {
                    mPresenter.createTask(
                            mTitle.getText().toString(),
                            mDescription.getText().toString());
                } else {
                    mPresenter.updateTask(
                            mTitle.getText().toString(),
                            mDescription.getText().toString());
                }
            }
        });

Shouldn't the view just pass the user action to presenter and let presenter decide?
As the presenter knows whether its a new task or a task update, this decision can be deferred to presenter and view does not have to store any information related to the task.
Thoughts?

Android Test Fail

some espresso tests fail.
android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with content description: is "Navigate up"

On todo-databinding, remove logic from layout files

Hey guys, thanks for the awesome repo and the samples!

Not sure if this is nitpicking or not but, even though the databinding lib offers quite an elaborate set of options to add logic directly into the layout files (example: determining the visibility of an element in statistics_frag.xml) I think that power should be relinquished to the Presenter since one is in place.

In essence, since the todo-databinding arch is based on MVP, it's probably more suitable to remove any logic from all layout files and put it in appropriate getters in the respective presenters (or ViewModels as depicted in README.md). Databinding will still be used in the layouts but only to connect to the presenter.

I could work on that goal if this gets a few 👍
Thanks! 😃 ❤️

sample: MVP-RxJava - suggestion

@ErikHellman I suggest to use a BaseFragment for collecting all subscriptions in a CompositeSubscription and unsubscribing in onPause().
Please let me know if I should create a PR to discuss this.

New sample: MVP-RxJava

Based on MVP but using RxJava for asynchronous jobs, event handling and data observation.

How should we deal with the growing repository in model layer?

In the todo project we simply have one POJO(Task) and we already have a bloated model layer here. It's quite common to have dozens of POJOs in a REAL project. And it's easy to imagine how big the repository would grow. Whenever I want to add amend something, like adding a Owner(of a Task), I have to add so many lines of code in each one of the classes in the model layer. No need to mention that we have to write so many hardcoded SQL statements.
Is there a better way to avoid these things?

Add tablet layout

A layout with multiple fragments per screen would showcase how to keep data fresh between views and send messages between presenters.

On todo-databinding, remove logic from layout files and use Custom Setter

I read the previous discussion #72 and understand the approach, but most layout logic could be replaced with @BindingAdapter annotation and people could see their power, one example

<TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@{stats.status}"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:visibility="@{stats.showStatus ? View.VISIBLE : View.GONE}" />

could be replaced with

<TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@{stats.status}"
        android:textAppearance="?android:attr/textAppearanceMedium"
        app:visibility_value="@{stats.showStatus}"

and

public class VisibilityBinding {
    @BindingAdapter({
            "visibility_value"
    })
    public static void bindVisibility(View view, boolean visible) {
        bindVisibility(visible, View.VISIBLE, View.GONE);
    }

    @BindingAdapter({
            "visibility_value",
            "visibility_off"
    })
    public static void bindVisibility(View view, boolean visible, int visibilityOffValue) {
        bindVisibility(visible, View.VISIBLE, visibilityOffValue);
    }

    @BindingAdapter({
            "visibility_value",
            "visibility_off",
            "visibility_on"
    })
    public static void bindVisibility(View view, boolean visible, int visibilityOffValue, int visibilityOnValue) {
        view.setVisibility(visible ? visibilityOnValue : visibilityOffValue);
    }

}

could even create binding app:hidden app:invisible first one use View.GONE for false value, second one use View.INVISIBLE that it's a better naming, and the only logic xml have it's negation mark !

<TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@{stats.status}"
        android:textAppearance="?android:attr/textAppearanceMedium"
        app:hidden="@{!stats.showStatus}"
public class VisibilityBinding {
    @BindingAdapter({
            "hidden"
    })
    public static void bindHiddenVisibility(View view, boolean hidden) {   
        view.setVisibility(hidden ? View.GONE : View.VISIBLE);
    }

   @BindingAdapter({
            "invisible"
    })
    public static void bindInvisibleVisibility(View view, boolean invisible) {   
        view.setVisibility(hidden ? View.INVISIBLE : View.VISIBLE);
    }
}

WDYT guys?

Presenters have links to TasksRepository. Todo-mvp.

I have a small question, about relation between Presenters and TaskRepository.

Why all Presenters, but AddEditTaskPresenter, have link directly to TasksRepository, instead of TasksDataSource? Using interface will make code a little bit more decoupled, since interface provides all required methods.

If this behaviour is intended, then, probably, AddEditTaskPresenter should also have link directly to TasksRepository.

Question - dev-todo-mvp-dagger-update

Hi all,
I have a question regarding the dagger-mvp-update branch.. I am trying to make a sample for rxjava+retrofit +dagger using the beautiful sample that you guys have provided. I saw for each fragment we have a fragment component and a module for that specific view..I really liked this idea but I was just concerned will this be same when i have 1 activity holding 10 fragment or more.. Also I wanted to ask is there any specific reason for starting the presenter cycle from on resume?
Also a huge thanks to you all for putting your efforts in making this beautiful sample👍

New sample: Flux-RxJava-Dagger2

Based on Flux but using RxJava for asynchronous jobs, event handling and data observation and
using Dagger2 for dependency injection.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.