标签:mvvm mvp data binding android
原文链接:new
ShowToastMessage("hello world")
. This will yield a greater separation of the view and the viewmodel – but is that a good thing?<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivityFragment"> <TextView android:text="..." android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:id="@+id/loggedInUserCount"/> <TextView android:text="# logged in users:" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="false" android:layout_toLeftOf="@+id/loggedInUserCount"/> <RadioGroup android:layout_marginTop="40dp" android:id="@+id/existingOrNewUser" android:gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:orientation="horizontal"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Returning user" android:id="@+id/returningUserRb"/> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New user" android:id="@+id/newUserRb" /> </RadioGroup> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/username_block" android:layout_below="@+id/existingOrNewUser"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Username:" android:id="@+id/textView" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/username" android:minWidth="200dp"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="false" android:id="@+id/password_block" android:layout_below="@+id/username_block"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Password:" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="textPassword" android:ems="10" android:id="@+id/password"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/password_block" android:id="@+id/email_block"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Email:" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:ems="10" android:id="@+id/email"/> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Log in" android:id="@+id/loginOrCreateButton" android:layout_below="@+id/email_block" android:layout_centerHorizontal="true"/> </RelativeLayout>
package com.nilzor.presenterexample; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.CompoundButton; import android.widget.RadioButton; import android.widget.TextView; import android.widget.Toast; import com.hannesdorfmann.mosby.mvp.MvpFragment; import com.hannesdorfmann.mosby.mvp.MvpView; import butterknife.InjectView; import butterknife.OnClick; public class MainActivityFragment extends MvpFragment implements MvpView { @InjectView(R.id.username) TextView mUsername; @InjectView(R.id.password) TextView mPassword; @InjectView(R.id.newUserRb) RadioButton mNewUserRb; @InjectView(R.id.returningUserRb) RadioButton mReturningUserRb; @InjectView(R.id.loginOrCreateButton) Button mLoginOrCreateButton; @InjectView(R.id.email_block) ViewGroup mEmailBlock; @InjectView(R.id.loggedInUserCount) TextView mLoggedInUserCount; public MainActivityFragment() { } @Override public MainPresenter createPresenter() { return new MainPresenter(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_main, container, false); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); attachEventListeners(); } private void attachEventListeners() { mNewUserRb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { updateDependentViews(); } }); mReturningUserRb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { updateDependentViews(); } }); } /** Prepares the initial state of the view upon startup */ public void setInitialState() { mReturningUserRb.setChecked(true); updateDependentViews(); } /** Shows/hides email field and sets correct text of login button depending on state of radio buttons */ public void updateDependentViews() { if (mReturningUserRb.isChecked()) { mEmailBlock.setVisibility(View.GONE); mLoginOrCreateButton.setText(R.string.log_in); } else { mEmailBlock.setVisibility(View.VISIBLE); mLoginOrCreateButton.setText(R.string.create_user); } } public void setNumberOfLoggedIn(int numberOfLoggedIn) { mLoggedInUserCount.setText("" + numberOfLoggedIn); } @OnClick(R.id.loginOrCreateButton) public void loginOrCreate() { if (mNewUserRb.isChecked()) { Toast.makeText(getActivity(), "Please enter a valid email address", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getActivity(), "Invalid username or password", Toast.LENGTH_SHORT).show(); } } }
package com.nilzor.presenterexample; import android.os.Handler; import android.os.Message; import com.hannesdorfmann.mosby.mvp.MvpPresenter; public class MainPresenter implements MvpPresenter { MainModel mModel; private MainActivityFragment mView; public MainPresenter() { mModel = new MainModel(); } @Override public void attachView(MainActivityFragment view) { mView = view; view.setInitialState(); updateViewFromModel(); ensureModelDataIsLoaded(); } @Override public void detachView(boolean retainInstance) { mView = null; } private void ensureModelDataIsLoaded() { if (!mModel.isLoaded()) { mModel.loadAsync(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { updateViewFromModel(); return true; } }); } } /** Notifies the views of the current value of "numberOfUsersLoggedIn", if any */ private void updateViewFromModel() { if (mView != null && mModel.isLoaded()) { mView.setNumberOfLoggedIn(mModel.numberOfUsersLoggedIn); } } }
package com.nilzor.presenterexample; import android.os.AsyncTask; import android.os.Handler; import java.util.Random; public class MainModel { public Integer numberOfUsersLoggedIn; private boolean mIsLoaded; public boolean isLoaded() { return mIsLoaded; } public void loadAsync(final Handler.Callback onDoneCallback) { new AsyncTask() { @Override protected Void doInBackground(Void... params) { // Simulating some asynchronous task fetching data from a remote server try {Thread.sleep(2000);} catch (Exception ex) {}; numberOfUsersLoggedIn = new Random().nextInt(1000); mIsLoaded = true; return null; } @Override protected void onPostExecute(Void aVoid) { onDoneCallback.handleMessage(null); } }.execute((Void) null); } }
<layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <data> <variable name="data" type="com.nilzor.presenterexample.MainModel"/> </data> <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivityFragment"> <TextView android:text="@{data.numberOfUsersLoggedIn}" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:id="@+id/loggedInUserCount"/> <TextView android:text="# logged in users:" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentEnd="false" android:layout_toLeftOf="@+id/loggedInUserCount"/> <RadioGroup android:layout_marginTop="40dp" android:id="@+id/existingOrNewUser" android:gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:orientation="horizontal"> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Returning user" android:checked="@{data.isExistingUserChecked}" android:id="@+id/returningUserRb"/> <RadioButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="New user" android:id="@+id/newUserRb" /> </RadioGroup> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:id="@+id/username_block" android:layout_below="@+id/existingOrNewUser"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Username:" android:id="@+id/textView" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/username" android:minWidth="200dp"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentStart="false" android:id="@+id/password_block" android:layout_below="@+id/username_block"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Password:" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="textPassword" android:ems="10" android:id="@+id/password"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/password_block" android:id="@+id/email_block" android:visibility="@{data.emailBlockVisibility}"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="Email:" android:minWidth="100dp"/> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="textEmailAddress" android:ems="10" android:id="@+id/email"/> </LinearLayout> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@{data.loginOrCreateButtonText}" android:id="@+id/loginOrCreateButton" android:layout_below="@+id/email_block" android:layout_centerHorizontal="true"/> </RelativeLayout> </layout>
package com.nilzor.presenterexample; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.Toast; import com.nilzor.presenterexample.databinding.FragmentMainBinding; public class MainActivityFragment extends Fragment { private FragmentMainBinding mBinding; private MainModel mViewModel; public MainActivityFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_main, container, false); mBinding = FragmentMainBinding.bind(view); mViewModel = new MainModel(this, getResources()); mBinding.setData(mViewModel); attachButtonListener(); return view; } private void attachButtonListener() { mBinding.loginOrCreateButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mViewModel.logInClicked(); } }); } @Override public void onViewCreated(View view, Bundle savedInstanceState) { ensureModelDataIsLodaded(); } private void ensureModelDataIsLodaded() { if (!mViewModel.isLoaded()) { mViewModel.loadAsync(); } } public void showShortToast(String text) { Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show(); } }
package com.nilzor.presenterexample; import android.content.res.Resources; import android.databinding.ObservableField; import android.os.AsyncTask; import android.view.View; import java.util.Random; public class MainModel { public ObservableField numberOfUsersLoggedIn = new ObservableField(); public ObservableField isExistingUserChecked = new ObservableField(); public ObservableField emailBlockVisibility = new ObservableField(); public ObservableField loginOrCreateButtonText = new ObservableField(); private boolean mIsLoaded; private MainActivityFragment mView; private Resources mResources; public MainModel(MainActivityFragment view, Resources resources) { mView = view; mResources = resources; // You might want to abstract this for testability setInitialState(); updateDependentViews(); hookUpDependencies(); } public boolean isLoaded() { return mIsLoaded; } private void setInitialState() { numberOfUsersLoggedIn.set("..."); isExistingUserChecked.set(true); } private void hookUpDependencies() { isExistingUserChecked.addOnPropertyChangedCallback(new android.databinding.Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(android.databinding.Observable sender, int propertyId) { updateDependentViews(); } }); } public void updateDependentViews() { if (isExistingUserChecked.get()) { emailBlockVisibility.set(View.GONE); loginOrCreateButtonText.set(mResources.getString(R.string.log_in)); } else { emailBlockVisibility.set(View.VISIBLE); loginOrCreateButtonText.set(mResources.getString(R.string.create_user)); } } public void loadAsync() { new AsyncTask() { @Override protected Void doInBackground(Void... params) { // Simulating some asynchronous task fetching data from a remote server try {Thread.sleep(2000);} catch (Exception ex) {}; numberOfUsersLoggedIn.set("" + new Random().nextInt(1000)); mIsLoaded = true; return null; } }.execute((Void) null); } public void logInClicked() { // Illustrating the need for calling back to the view though testable interfaces. if (isExistingUserChecked.get()) { mView.showShortToast("Invalid username or password"); } else { mView.showShortToast("Please enter a valid email address"); } } }
Android Databinding:再见Presenter,你好ViewModel
标签:mvvm mvp data binding android
原文地址:http://blog.csdn.net/easion_zms/article/details/47081949