» » » Android Architecture Components. 4. ViewModel

 

Android Architecture Components. 4. ViewModel

: admin 5-08-2017, 18:35, : 254

Android Architecture Components.  4. ViewModel



ViewModel , , , , , .. , onSaveInstanceState, , , , , ViewModel . , ViewModel , , ( , - ). , ViewModel Activity(Fragment).



: ViewModel, AndroidViewModel, ViewModelProvider, ViewModelProviders, ViewModelStore, ViewModelStores. ViewModel, AndroidViewModel ViewModelProviders, , .



ViewModel, , protected onCleared(). ViewModel, ViewModel . , onCleared(), ViewModel . , LiveData, observeForever(Observer), , onCleared() . , , View Context Activity ViewModel. , ViewModel . : (Activity/Fragment) ? LiveData, LiveData, , , ProgressBar, MutableLiveData ViewModel. :



public class MyViewModel extends ViewModel {
private MutableLiveData<Boolean> showProgress = new MutableLiveData<>();

//new thread
public void doSomeThing(){
showProgress.postValue(true);
...
showProgress.postValue(false);
}

public MutableLiveData<Boolean> getProgressState(){
return showProgress;
}
}


ViewModel ViewModelProviders:



@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final MyViewModel viewModel = ViewModelProviders.of(this).get(MyViewModel.class);
viewModel.getProgressState().observe(this, new Observer<Boolean>() {
@Override
public void onchanged(@Nullable Boolean aBoolean) {
if (aBoolean) {
showProgress();
} else {
hideProgress();
}
}
});
viewModel.doSomeThing();
}


AndroidViewModel, ViewModel, Application. , Location Service , Application Context. , ViewModel ApplicationViewModel. Activity/Fragment , ViewModel.



ViewModelProviders, , , of ViewModelProvider. Activity Fragment, , ViewModelProvider.Factory, DefaultFactory, ViewModelProviders. android.arch .



ViewModelProvider, , ViewModel. , ViewModelStore, , ViewModel get, get(Class) get(String key, Class modelClass). , ViewModel Activity/Fragment . get String key, : android.arch.lifecycle.ViewModelProvider.DefaultKey: + canonicalName



ViewModelStores, , : , , , , , . , android.arch , ViewModelStore.



ViewModelStore, , put, get clear. , , get put , default (package-private), . , , . HashMap, get put, , ( , ViewModelProvider) ViewModel. clear(), onCleared() ViewModel .



ViewModel , , , . WiFi network, , , .



Android Architecture Components.  4. ViewModel

LiveData WiFi :



public class LocationLiveData extends LiveData<Location> implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,
LocationListener {
private final static int UPDATE_INTERVAL = 1000;
private GoogleApiClient googleApiClient;

public LocationLiveData(Context context) {
googleApiClient =
new GoogleApiClient.Builder(context, this, this)
.addApi(LocationServices.API)
.build();
}

@Override
protected void onActive() {
googleApiClient.connect();
}

@Override
protected void onInactive() {
if (googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(
googleApiClient, this);
}
googleApiClient.disconnect();
}

@Override
public void onConnected(Bundle connectionHint) {
LocationRequest locationRequest = new LocationRequest().setInterval(UPDATE_INTERVAL).setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationServices.FusedLocationApi.requestLocationUpdates(
googleApiClient, locationRequest, this);
}

@Override
public void onLocationchanged(Location location) {
setValue(location);
}

@Override
public void onConnectionSuspended(int cause) {
setValue(null);
}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
setValue(null);
}
}



public class NetworkLiveData extends LiveData<String> {
private Context context;
private BroadcastReceiver broadcastReceiver;

public NetworkLiveData(Context context) {
this.context = context;
}

private void prepareReceiver(Context context) {
IntentFilter filter = new IntentFilter();
filter.addAction("android.net.wifi.supplicant.CONNECTION_CHANGE");
filter.addAction("android.net.wifi.STATE_CHANGE");
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
WifiManager wifiMgr = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wifiMgr.getConnectionInfo();
String name = wifiInfo.getSSID();
if (name.isEmpty()) {
setValue(null);
} else {
setValue(name);
}
}
};
context.registerReceiver(broadcastReceiver, filter);
}

@Override
protected void onActive() {
super.onActive();
prepareReceiver(context);
}

@Override
protected void onInactive() {
super.onInactive();
context.unregisterReceiver(broadcastReceiver);
broadcastReceiver = null;
}
}


ViewModel, , LifeData, MediatorLiveData , , MediatorLiveData observeForever. onCleared() removeObserver. LiveData MutableLiveData, .



public class DetectorViewModel extends AndroidViewModel {
//   ,   Repository,      GitHub     
private IRepository repository;
private LatLng point;
private int radius;
private LocationLiveData locationLiveData;
private NetworkLiveData networkLiveData;
private MediatorLiveData<Status> statusMediatorLiveData = new MediatorLiveData<>();
private MutableLiveData<String> statusLiveData = new MutableLiveData<>();
private String networkName;
private float[] distance = new float[1];
private Observer<Location> locationObserver = new Observer<Location>() {
@Override
public void onchanged(@Nullable Location location) {
checkZone();
}
};
private Observer<String> networkObserver = new Observer<String>() {
@Override
public void onchanged(@Nullable String s) {
checkZone();
}
};
private Observer<Status> mediatorStatusObserver = new Observer<Status>() {
@Override
public void onchanged(@Nullable Status status) {
statusLiveData.setValue(status.toString());
}
};

public DetectorViewModel(final Application application) {
super(application);
repository = Repository.getInstance(application.getApplicationContext());
initVariables();
locationLiveData = new LocationLiveData(application.getApplicationContext());
networkLiveData = new NetworkLiveData(application.getApplicationContext());
statusMediatorLiveData.addSource(locationLiveData, locationObserver);
statusMediatorLiveData.addSource(networkLiveData, networkObserver);
statusMediatorLiveData.observeForever(mediatorStatusObserver);
}

//      LocationService  ,      WiFi network .
private void updateLocationService() {
if (isRequestedWiFi()) {
statusMediatorLiveData.removeSource(locationLiveData);
} else if (!isRequestedWiFi() && !locationLiveData.hasActiveObservers()) {
statusMediatorLiveData.addSource(locationLiveData, locationObserver);
}
}

//   
private void initVariables() {
point = repository.getPoint();
if (point.latitude == 0 && point.longitude == 0)
point = null;
radius = repository.getRadius();
networkName = repository.getNetworkName();
}

//,            
private void checkZone() {
updateLocationService();
if (isRequestedWiFi() || isInRadius()) {
statusMediatorLiveData.setValue(Status.INSIDE);
} else {
statusMediatorLiveData.setValue(Status.OUTSIDE);
}
}

public LiveData<String> getStatus() {
return statusLiveData;
}
//        
public void savePoint(LatLng latLng) {
repository.savePoint(latLng);
point = latLng;
checkZone();
}

public void saveRadius(int radius) {
this.radius = radius;
repository.saveRadius(radius);
checkZone();
}

public void saveNetworkName(String networkName) {
this.networkName = networkName;
repository.saveNetworkName(networkName);
checkZone();
}

public int getRadius() {
return radius;
}

public LatLng getPoint() {
return point;
}

public String getNetworkName() {
return networkName;
}

public boolean isInRadius() {
if (locationLiveData.getValue() != null && point != null) {
Location.distanceBetween(locationLiveData.getValue().getLatitude(), locationLiveData.getValue().getLongitude(), point.latitude, point.longitude, distance);
if (distance[0] <= radius)
return true;
}
return false;
}

public boolean isRequestedWiFi() {
if (networkLiveData.getValue() == null)
return false;
if (networkName.isEmpty())
return false;
String network = networkName.replace(""", "").toLowerCase();
String currentNetwork = networkLiveData.getValue().replace(""", "").toLowerCase();
return network.equals(currentNetwork);
}

@Override
protected void onCleared() {
super.onCleared();
statusMediatorLiveData.removeSource(locationLiveData);
statusMediatorLiveData.removeSource(networkLiveData);
statusMediatorLiveData.removeObserver(mediatorStatusObserver);
}
}


:



public class MainActivity extends LifecycleActivity {
private static final int PERMISSION_LOCATION_REQUEST = 0001;
private static final int PLACE_PICKER_REQUEST = 1;
private static final int GPS_ENABLE_REQUEST = 2;
@BindView(R.id.status)
TextView statusView;
@BindView(R.id.radius)
EditText radiusEditText;
@BindView(R.id.point)
EditText pointEditText;
@BindView(R.id.network_name)
EditText networkEditText;
@BindView(R.id.warning_container)
ViewGroup warningContainer;
@BindView(R.id.main_content)
ViewGroup contentContainer;
@BindView(R.id.permission)
Button permissionButton;
@BindView(R.id.gps)
Button gpsButton;
private DetectorViewModel viewModel;
private LatLng latLng;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
checkPermission();
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
init();
} else {
showWarningPage(Warning.PERMISSION);
}
}

private void checkPermission() {
if (PackageManager.PERMISSION_GRANTED == checkSelfPermission(
Manifest.permission.ACCESS_FINE_LOCATION)) {
init();
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, PERMISSION_LOCATION_REQUEST);
}
}


private void init() {
viewModel = ViewModelProviders.of(this).get(DetectorViewModel.class);
if (Utils.isGpsEnabled(this)) {
hideWarningPage();
checkingPosition();
initInput();
} else {
showWarningPage(Warning.GPS_DISABLED);
}
}

private void initInput() {
radiusEditText.setText(String.valueOf(viewModel.getRadius()));
latLng = viewModel.getPoint();
if (latLng == null) {
pointEditText.setText(getString(R.string.chose_point));
} else {
pointEditText.setText(latLng.toString());
}
networkEditText.setText(viewModel.getNetworkName());
}

@onclick(R.id.get_point)
void getPointClick(View view) {
PlacePicker.IntentBuilder builder = new PlacePicker.IntentBuilder();
try {
startActivityForResult(builder.build(MainActivity.this), PLACE_PICKER_REQUEST);
} catch (GooglePlayServicesRepairableException e) {
e.printStackTrace();
} catch (GooglePlayServicesNotAvailableException e) {
e.printStackTrace();
}
}

@onclick(R.id.save)
void saveonclick(View view) {
if (!TextUtils.isEmpty(radiusEditText.getText())) {
viewModel.saveRadius(Integer.parseInt(radiusEditText.getText().toString()));
}
viewModel.saveNetworkName(networkEditText.getText().toString());
}

@onclick(R.id.permission)
void permissiononclick(View view) {
checkPermission();
}

@onclick(R.id.gps)
void gpsonclick(View view) {
startActivityForResult(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS), GPS_ENABLE_REQUEST);
}


private void checkingPosition() {
viewModel.getStatus().observe(this, new Observer<String>() {
@Override
public void onchanged(@Nullable String status) {
updateUI(status);
}
});
}

private void updateUI(String status) {
statusView.setText(status);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PLACE_PICKER_REQUEST) {
if (resultCode == RESULT_OK) {
Place place = PlacePicker.getPlace(data, this);
updatePlace(place.getLatLng());
}
}
if (requestCode == GPS_ENABLE_REQUEST) {
init();
}
}

private void updatePlace(LatLng latLng) {
viewModel.savePoint(latLng);
pointEditText.setText(latLng.toString());
}

private void showWarningPage(Warning warning) {
warningContainer.setVisibility(View.VISIBLE);
contentContainer.setVisibility(View.INVISIBLE);
switch (warning) {
case PERMISSION:
gpsButton.setVisibility(View.INVISIBLE);
permissionButton.setVisibility(View.VISIBLE);
break;
case GPS_DISABLED:
gpsButton.setVisibility(View.VISIBLE);
permissionButton.setVisibility(View.INVISIBLE);
break;
}
}

private void hideWarningPage() {
warningContainer.setVisibility(View.GONE);
contentContainer.setVisibility(View.VISIBLE);
}
}


MutableLiveData, n getStatus() ViewModel. .



, RuntimePermission GPS. , Activity , UI, ( ).



:



compile 'com.jakewharton:butterknife:8.6.0'
compile 'com.google.android.gms:play-services-maps:11.0.2'
compile 'com.google.android.gms:play-services-location:11.0.2'
compile 'com.google.android.gms:play-services-places:11.0.2'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'


: here



: here here



Android Architecture Components. 1.

Android Architecture Components. 2. Lifecycle

Android Architecture Components. 3. LiveData

Android Architecture Components. 4. ViewModel


:

: -, Game Development, Android

, .
.

:*
E-Mail:
:
| | |
, : *