package uk.ivanc.archimvvm.viewmodel; import android.content.Context; import android.databinding.ObservableField; import android.databinding.ObservableInt; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.KeyEvent; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.TextView; import java.util.List; import retrofit2.adapter.rxjava.HttpException; import rx.Subscriber; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; import uk.ivanc.archimvvm.ArchiApplication; import uk.ivanc.archimvvm.R; import uk.ivanc.archimvvm.model.GithubService; import uk.ivanc.archimvvm.model.Repository; /** * View model for the MainActivity */ public class MainViewModel implements ViewModel { private static final String TAG = "MainViewModel"; public ObservableInt infoMessageVisibility; public ObservableInt progressVisibility; public ObservableInt recyclerViewVisibility; public ObservableInt searchButtonVisibility; public ObservableField<String> infoMessage; private Context context; private Subscription subscription; private List<Repository> repositories; private DataListener dataListener; private String editTextUsernameValue; public MainViewModel(Context context, DataListener dataListener) { this.context = context; this.dataListener = dataListener; infoMessageVisibility = new ObservableInt(View.VISIBLE); progressVisibility = new ObservableInt(View.INVISIBLE); recyclerViewVisibility = new ObservableInt(View.INVISIBLE); searchButtonVisibility = new ObservableInt(View.GONE); infoMessage = new ObservableField<>(context.getString(R.string.default_info_message)); } public void setDataListener(DataListener dataListener) { this.dataListener = dataListener; } @Override public void destroy() { if (subscription != null && !subscription.isUnsubscribed()) subscription.unsubscribe(); subscription = null; context = null; dataListener = null; } public boolean onSearchAction(TextView view, int actionId, KeyEvent event) { if (actionId == EditorInfo.IME_ACTION_SEARCH) { String username = view.getText().toString(); if (username.length() > 0) loadGithubRepos(username); return true; } return false; } public void onClickSearch(View view) { loadGithubRepos(editTextUsernameValue); } public TextWatcher getUsernameEditTextWatcher() { return new TextWatcher() { @Override public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) { } @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) { editTextUsernameValue = charSequence.toString(); searchButtonVisibility.set(charSequence.length() > 0 ? View.VISIBLE : View.GONE); } @Override public void afterTextChanged(Editable editable) { } }; } private void loadGithubRepos(String username) { progressVisibility.set(View.VISIBLE); recyclerViewVisibility.set(View.INVISIBLE); infoMessageVisibility.set(View.INVISIBLE); if (subscription != null && !subscription.isUnsubscribed()) subscription.unsubscribe(); ArchiApplication application = ArchiApplication.get(context); GithubService githubService = application.getGithubService(); subscription = githubService.publicRepositories(username) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(application.defaultSubscribeScheduler()) .subscribe(new Subscriber<List<Repository>>() { @Override public void onCompleted() { if (dataListener != null) dataListener.onRepositoriesChanged(repositories); progressVisibility.set(View.INVISIBLE); if (!repositories.isEmpty()) { recyclerViewVisibility.set(View.VISIBLE); } else { infoMessage.set(context.getString(R.string.text_empty_repos)); infoMessageVisibility.set(View.VISIBLE); } } @Override public void onError(Throwable error) { Log.e(TAG, "Error loading GitHub repos ", error); progressVisibility.set(View.INVISIBLE); if (isHttp404(error)) { infoMessage.set(context.getString(R.string.error_username_not_found)); } else { infoMessage.set(context.getString(R.string.error_loading_repos)); } infoMessageVisibility.set(View.VISIBLE); } @Override public void onNext(List<Repository> repositories) { Log.i(TAG, "Repos loaded " + repositories); MainViewModel.this.repositories = repositories; } }); } private static boolean isHttp404(Throwable error) { return error instanceof HttpException && ((HttpException) error).code() == 404; } public interface DataListener { void onRepositoriesChanged(List<Repository> repositories); } }