Giter VIP home page Giter VIP logo

ground-android's Introduction

Ground for Android

cloud build status codecov.io Open Source Helpers

Ground is an open-source, map-first data collection and analysis platform built to seamlessly connect the offline world with cloud-based storage and computation. The platform consists of a web app for data management and an Android app for offline data collection. Our goal is to provide a "just right" data collection solution that meets the needs of community organizers, conservationists, humanitarian workers, and researchers addressing some of today's most pressing issues.

Note: Ground is not an officially supported Google product, and is developed on a best-effort basis.

You can learn more about Ground on the project website.

Contributing

We'd love to accept your patches and contributions to this project. For more information, including details on the required Contributor License Agreement (CLA), code reviews, and environment setup, see Contributing to Ground for Android.

ground-android's People

Contributors

anandwana001 avatar arun-kushwaha04 avatar chinesco avatar devedroy avatar dturner avatar emmanueldav avatar gino-m avatar hoc081098 avatar jsunde avatar justinkimtang avatar mmisim avatar navinsivakumar avatar nmayorga092 avatar nmhung00 avatar recursive-knot avatar scolsen avatar shobhitagarwal1612 avatar sufyanabbasi avatar yongsuk44 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

ground-android's Issues

[Docs] Document issue creation process

Once we've determined the best process for creating new issues, we should document it in CONTRIBUTING.md (On the issues page, a message from github recommends reading this file prior to creating an issue, so it makes sense to include issue creation guidelines here).

Should we decide not to document this process, we can capture discussions on the matter here and close this issue once it's settled.

[Code health] Rename Place(Type) to Feature(Type) throughout

Backpeddling on this one after looking at other related tools and after feedback at G4G18. "Feature" is also more correct, since it includes any type of entity on a map, whereas "Place" can be misunderstood as a single point instead of any arbitrary feature (polygons, polylines, etc.).

Keep RX Streams as "Pure" as Possible?

At the moment, there are some places in which streams and so called "side effects" (operations that use some value from the stream but don't modify the stream's contents i.e. aren't operations like map, and co.) are intermingled. For example, the addFeatureDialogFragment.show function:

Observable<Feature> featureStream =
        showFeatureDialogRequests.flatMapMaybe(
            fragmentManager -> addFeatureDialogFragment.show(fragmentManager));

does two things: it calls show on the fragmentManager, and returns an entirely new PublishSubject:

public Maybe<Feature> show(FragmentManager fragmentManager) {
    addFeatureRequestSubject = MaybeSubject.create();
    show(fragmentManager, TAG);
    return addFeatureRequestSubject;
  }

This obfuscates the semantics somewhat and makes reading some functions difficult. For example, I would expect show to be "effectful" only, and not to return a new Maybe.

Instead we can refactor this to use RX semantics to achieve the same thing.

Observable<Feature> featureStream =
        showFeatureDialogRequests.doOnNext(fragmentManager -> show(fragmentManager, TAG)).flatMapMaybe(__ -> addFeatureDialogFragment.toSubject());

An approach like this keeps side effects and transformations separate and immediately obvious when reading the sequence of stream operations. This way we can essentially keep data transformations and ui actions 'distinct'.

This is preferential of course, so please let me know if you disagree!

[Code health] Verify usage of Rx side effects

There are some instances in the code in which we rely on doOnNext, doOnSuccess and other RX side effect operators.

In general, we should either avoid side effects entirely or ensure their usage is carefully prescribed.

Personally, I like treating anything that does not have to do with the direct manipulation of data (emitted items) as a side effect. For example, logging and UI changes would both be considered side effects from this perspective. I think this approach enables us to maintain clear separation between the actual 'transformation'/ data-manipulating code and 'side-effecting' code like logging.

For our purposes, we only need to treat logging as a side-effect, since display related code is handled by fragments (and ideally live-data binding). The majority of cases in which we manipulate some piece of data in a doOn function can be expressed using transformations instead.

@gino-m

[Code health] Update usage of Rx streams to stop accumulating subscriptions

In many cases we subscribe to a Completable, Single, or Maybe, and keeping around the Disposable for the lifetime of the component (ViewModel, View), leaking memory.

Example:
https://github.com/google/gnd-android/blob/5d87d022dd6e08a308309c93a34dc2ad97a5e195/gnd/src/main/java/com/google/android/gnd/ui/recorddetails/RecordDetailsViewModel.java#L42-L45

Rather than subscribing to the returned Maybe returned by getRecordDetails() and calling setValue on the MutableLiveData, is it possible to merge the Maybe into a existing stream in a such way that subscription is properly managed? If not, how should short-lived Single/Maybe/Completable subscriptions be disposed? I've seen conflicting suggestions online, from keeping them around in a CompositeDisposable (for the lifetime of the View?) to assuming Rx automatically disposes of them.

[Offline support] Allow user to add/remove accounts for offline use

The prototype currently requests sign-in when opening the app. If the user signs out while offline, the app currently becomes unusable, since there's no way to log back in. In order to properly support offline use, account tokens will likely need to be stored locally.

  • Ensure workers connect to remote using user initiating mutation, not current user
  • When user removed, also remove all pending mutations
  • Verify error handling and race conditions when syncing mutations from deleted users
  • List users UI
  • Add user UI
  • Remove user UI

[Datastore] Ignore invalid or incomplete data in Firebase

Motivation: Once first Android binaries are rolled out, we won't be able to make breaking changes to the database. Making client more resilient to invalid or missing data in Firebase will allow us more flexibility in adding and deprecating features in the db

Use RX semantics for fragment interactions?

Yet another stylistic/preferential question--forgive me for having so many of these but once they're firmly answered I'll move forward without causing any trouble!

We've recently had some discussions about naming subjects that track user interactions appropriately such as (addFeatureClicks) etc. Most of these currently (or will) live in viewmodels as subjects. However, I think it may be more appropriate to track interactions (clicks, etc) in the fragment, granting the view models some level of independence.

This is already the case in some sense, but we currently often mix RX methods and approaches with more traditional direct VM method calls etc. Instead, we can stick to RX as much as possible, creating observables/subjects to track fragment interactions and capturing responses to view model data as transformations on these interactions.

see 4491816 experimental/scolsen/observable-views for an example using this approach.

For reference, here's a relevant snippet from the previously mentioned commit:

First, we specify the appropriate fragment reaction in the onCreate method and subscribe to the stream:

  @Override
  public void onCreate(@androidx.annotation.Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    saveClicks = PublishSubject.create();
    singleSelectDialogFactory = new SingleSelectDialogFactory(getContext());
    multiSelectDialogFactory = new MultiSelectDialogFactory(getContext());
    viewModel = getViewModel(EditRecordViewModel.class);

    Observable<Boolean> saveClickReactions =
        saveClicks
            .map(__ -> viewModel.onSaveClick())
            .doOnNext(
                result -> {
                  if (!result) {
                    EphemeralPopups.showFyi(getContext(), R.string.no_changes_to_save);
                    navigator.navigateUp();
                  }
                });

    saveClickReactions.subscribe();

Second, when a user clicks, drags, w/e, we emit:

  @OnClick(R.id.save_record_btn)
  void onSaveClick() {
    saveClicks.onNext(new Object());
  }

Note that this is mostly a stylistic difference and it may be totally unnecessary if we're able to switch every fragment/VM data coupling to LiveData bindings. This approach does grant us some additional flexibility in that it's now fairly straightforward to accumulate further transformations/interactions on the initial stream, and it eliminates the need to track any state for dependent reactions (if any exist, we can simply model them as transformations, merges, etc.).

It also frees up

[Code health] Consistent naming of Rx streams

@scolsen listened to this podcast after our chat. I agree with most of the suggestions there. Key takeaways (mixed with my own observations):

  • There's no single convention used by everyone, but there are some prevailing trends.
  • The getFoo() pattern is dated, a relic of JavaBeans naming conventions.
  • Consistent naming >> relying on return types as documentation:
  • Doesn't require developers to look at declaration to understand semantics.
  • Prevents signatures from collide if we add an override that returns a different Rx type.

Some ideas/suggestions:

  • Use foo() for immutable synchronous accessors (e.g. User user()).. There's also precedent for this in JDK methods like values().
  • fooOnce() for Rx types that return a single value and complete (usually Single<>).
  • fooStream() for Rx types that are expected to not complete while the application is in a normal state.
    fooOnceAndStream()` for Rx types that return a single value (the latest?) ASAP and then continue to stream updates while the application is in a normal state.

A similar approach is also described here.

Wdyt? No need to change existing uses now, but new code could use the convention, and we can update existing code once V0 is ready.

@navinsivakumar FYI.

[Code health] Consolidate local and remote db services

Currently, local db impl using Room lives in com.google.android.gnd.repository.local.

The remote db interface is in com.google.android.gnd.service.RemoteDataService, with Firestore impl under com.google.android.gnd.service.firestore.

This is inconsistent and arbitrary. I would suggest renaming and moving as follows:

  • Remote db interface: com.google.android.gnd.service.remotedb.RemoteDbService
  • Remote db impl: com.google.android.gnd.service.remotedb.firestore.*
  • Local db interface: com.google.android.gnd.service.localdb.LocalDbService (TBD)
  • Local db impl: com.google.android.gnd.service.localdb.room.*

@scolsen, @navinsivakumar, any thoughts?

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.