Repository: SpikeKing/TestDetailRxAndroid Branch: master Commit: cb8bbbd77fc4 Files: 53 Total size: 54.9 KB Directory structure: gitextract_61_m6m3q/ ├── .gitignore ├── .idea/ │ ├── .name │ ├── compiler.xml │ ├── copyright/ │ │ └── profiles_settings.xml │ ├── dictionaries/ │ │ └── wangchenlong.xml │ ├── encodings.xml │ ├── gradle.xml │ ├── misc.xml │ ├── modules.xml │ ├── runConfigurations.xml │ └── vcs.xml ├── README.md ├── app/ │ ├── .gitignore │ ├── build.gradle │ ├── proguard-rules.pro │ └── src/ │ ├── androidTest/ │ │ └── java/ │ │ └── org/ │ │ └── wangchenlong/ │ │ └── testdetailrxandroid/ │ │ └── ApplicationTest.java │ ├── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── org/ │ │ │ └── wangchenlong/ │ │ │ └── testdetailrxandroid/ │ │ │ ├── BindingActivity.java │ │ │ ├── LambdaActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── MoreActivity.java │ │ │ ├── NetworkActivity.java │ │ │ ├── NetworkDetailActivity.java │ │ │ ├── SafeActivity.java │ │ │ ├── SimpleActivity.java │ │ │ └── networks/ │ │ │ ├── GitHubService.java │ │ │ ├── NetworkWrapper.java │ │ │ ├── RepoListAdapter.java │ │ │ ├── ServiceFactory.java │ │ │ └── UserListAdapter.java │ │ └── res/ │ │ ├── drawable/ │ │ │ └── ic_person_black_24dp.xml │ │ ├── layout/ │ │ │ ├── activity_binding.xml │ │ │ ├── activity_main.xml │ │ │ ├── activity_network.xml │ │ │ ├── activity_simple.xml │ │ │ ├── content_rxbinding.xml │ │ │ ├── item_network_repo.xml │ │ │ └── item_network_user.xml │ │ ├── menu/ │ │ │ └── menu_rxbinding.xml │ │ ├── values/ │ │ │ ├── colors.xml │ │ │ ├── dimens.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ │ ├── values-v21/ │ │ │ └── styles.xml │ │ └── values-w820dp/ │ │ └── dimens.xml │ └── test/ │ └── java/ │ └── org/ │ └── wangchenlong/ │ └── testdetailrxandroid/ │ └── ExampleUnitTest.java ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat └── settings.gradle ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ *.iml .gradle /local.properties /.idea/workspace.xml /.idea/libraries .DS_Store /build /captures ================================================ FILE: .idea/.name ================================================ TestDetailRxAndroid ================================================ FILE: .idea/compiler.xml ================================================ ================================================ FILE: .idea/copyright/profiles_settings.xml ================================================ ================================================ FILE: .idea/dictionaries/wangchenlong.xml ================================================ rxbinding snackbar ================================================ FILE: .idea/encodings.xml ================================================ ================================================ FILE: .idea/gradle.xml ================================================ ================================================ FILE: .idea/misc.xml ================================================ Android > Lint > Correctness C/C++ Data flow issuesJava General Java Unused codeC/C++ Android $USER_HOME$/.subversion 1.8 ================================================ FILE: .idea/modules.xml ================================================ ================================================ FILE: .idea/runConfigurations.xml ================================================ ================================================ FILE: .idea/vcs.xml ================================================ ================================================ FILE: README.md ================================================ # TestDetailRxAndroid RxAndroid的开发完整样例,Created by C.L. Wang ================================================ FILE: app/.gitignore ================================================ /build ================================================ FILE: app/build.gradle ================================================ plugins { id "me.tatarka.retrolambda" version "3.2.4" } apply plugin: 'com.android.application' android { compileSdkVersion 23 buildToolsVersion '25.0.0' defaultConfig { applicationId "org.wangchenlong.testdetailrxandroid" minSdkVersion 17 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.1.1' compile 'com.android.support:recyclerview-v7:23.1.1' // RecyclerView compile 'com.jakewharton:butterknife:7.0.1' // ButterKnife标注 compile 'io.reactivex:rxandroid:1.1.0' // RxAndroid compile 'io.reactivex:rxjava:1.1.0' // 推荐同时加载RxJava compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' // Retrofit网络处理 compile 'com.squareup.retrofit:adapter-rxjava:2.0.0-beta2' // Retrofit的rx解析库 compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' // Retrofit的gson库 compile 'com.squareup.picasso:picasso:2.5.2' // Picasso网络图片加载 compile 'com.trello:rxlifecycle:0.4.0' // RxLifecycle管理Rx的生命周期 compile 'com.trello:rxlifecycle-components:0.4.0' // RxLifecycle组件 // RxBinding compile 'com.jakewharton.rxbinding:rxbinding:0.3.0' compile 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.3.0' compile 'com.jakewharton.rxbinding:rxbinding-design:0.3.0' } ================================================ FILE: app/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/wangchenlong/Installations/android-sdk/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: app/src/androidTest/java/org/wangchenlong/testdetailrxandroid/ApplicationTest.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.app.Application; import android.test.ApplicationTestCase; /** * Testing Fundamentals */ public class ApplicationTest extends ApplicationTestCase { public ApplicationTest() { super(Application.class); } } ================================================ FILE: app/src/main/AndroidManifest.xml ================================================ ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/BindingActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.design.widget.FloatingActionButton; import android.support.design.widget.Snackbar; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.text.Editable; import android.text.TextWatcher; import android.view.Menu; import android.view.MenuItem; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; import com.jakewharton.rxbinding.support.design.widget.RxSnackbar; import com.jakewharton.rxbinding.support.v7.widget.RxToolbar; import com.jakewharton.rxbinding.view.RxView; import com.jakewharton.rxbinding.widget.RxTextView; import butterknife.Bind; import butterknife.ButterKnife; /** * Rx绑定 *

* Created by wangchenlong on 16/1/25. */ public class BindingActivity extends AppCompatActivity { @Bind(R.id.rxbinding_t_toolbar) Toolbar mTToolbar; @Bind(R.id.rxbinding_fab_fab) FloatingActionButton mFabFab; @Bind(R.id.rxbinding_et_usual_approach) EditText mEtUsualApproach; @Bind(R.id.rxbinding_et_reactive_approach) EditText mEtReactiveApproach; @Bind(R.id.rxbinding_tv_show) TextView mTvShow; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_binding); ButterKnife.bind(this); initToolbar(); // 初始化Toolbar initFabButton(); // 初始化Fab按钮 initEditText(); // 初始化编辑文本 } private void initToolbar() { setSupportActionBar(mTToolbar); // 添加Toolbar RxToolbar.itemClicks(mTToolbar).subscribe(this::onToolbarItemClicked); } private void onToolbarItemClicked(MenuItem menuItem) { String m = "点击\"" + menuItem.getTitle() + "\""; Toast.makeText(this, m, Toast.LENGTH_SHORT).show(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_rxbinding, menu); return super.onCreateOptionsMenu(menu); } // 初始化Fab按钮 private void initFabButton() { RxView.clicks(mFabFab).subscribe(this::onFabClicked); } // 点击Fab按钮 private void onFabClicked(Void v) { Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), "点击Snackbar", Snackbar.LENGTH_SHORT); snackbar.show(); RxSnackbar.dismisses(snackbar).subscribe(this::onSnackbarDismissed); } // 销毁Snackbar, event参考{Snackbar} private void onSnackbarDismissed(int event) { String text = "Snackbar消失代码:" + event; Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } // 初始化编辑文本 private void initEditText() { // 正常方式 mEtUsualApproach.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { mTvShow.setText(s); } @Override public void afterTextChanged(Editable s) { } }); // Rx方式 RxTextView.textChanges(mEtReactiveApproach).subscribe(mTvShow::setText); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/LambdaActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.widget.Toast; import java.util.Arrays; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; /** * Lambda表达式写法 *

* Created by wangchenlong on 15/12/31. */ public class LambdaActivity extends Activity { @Bind(R.id.simple_tv_text) TextView mTvText; final String[] mManyWords = {"Hello", "I", "am", "your", "friend", "Spike"}; final List mManyWordList = Arrays.asList(mManyWords); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple); ButterKnife.bind(this); // 添加字符串, 省略Action的其他方法, 只使用一个onNext. Observable obShow = Observable.just(sayMyName()); // 先映射, 再设置TextView obShow.observeOn(AndroidSchedulers.mainThread()) .map(String::toUpperCase).subscribe(mTvText::setText); // 单独显示数组中的每个元素 Observable obMap = Observable.from(mManyWords); // 映射之后分发 obMap.observeOn(AndroidSchedulers.mainThread()) .map(String::toUpperCase) .subscribe(this::showToast); // 优化过的代码, 直接获取数组, 再分发, 再合并, 再显示toast, Toast顺次执行. Observable.just(mManyWordList) .observeOn(AndroidSchedulers.mainThread()) .flatMap(Observable::from) .reduce(this::mergeString) .subscribe(this::showToast); // .subscribe(s -> showToast(s)); } // 创建字符串 private String sayMyName() { return "Hello, I am your friend, Spike!"; } // 显示Toast private void showToast(String s) { Toast.makeText(LambdaActivity.this, s, Toast.LENGTH_SHORT).show(); } // 合并字符串 private String mergeString(String s1, String s2) { return String.format("%s %s", s1, s2); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/MainActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.content.Intent; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; /** * 主Activity, 用于跳转各个模块. * * @author wangchenlong */ public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } // 跳转简单的页面 public void gotoSimpleModule(View view) { startActivity(new Intent(this, SimpleActivity.class)); } // 跳转复杂的页面 public void gotoMoreModule(View view) { startActivity(new Intent(this, MoreActivity.class)); } // 跳转Lambda的页面 public void gotoLambdaModule(View view) { startActivity(new Intent(this, LambdaActivity.class)); } // 跳转网络的页面 public void gotoNetworkModule(View view) { startActivity(new Intent(this, NetworkActivity.class)); } // 跳转线程安全的页面 public void gotoSafeModule(View view) { startActivity(new Intent(this, SafeActivity.class)); } // 跳转RxBinding的页面 public void gotoBindingModule(View view) { startActivity(new Intent(this, BindingActivity.class)); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/MoreActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.widget.Toast; import java.util.Arrays; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.functions.Action1; import rx.functions.Func1; import rx.functions.Func2; /** * 更多的RxAndroid的使用方法. *

* Created by wangchenlong on 15/12/30. */ public class MoreActivity extends Activity { @Bind(R.id.simple_tv_text) TextView mTvText; final String[] mManyWords = {"Hello", "I", "am", "your", "friend", "Spike"}; final List mManyWordList = Arrays.asList(mManyWords); // Action类似订阅者, 设置TextView private Action1 mTextViewAction = new Action1() { @Override public void call(String s) { mTvText.setText(s); } }; // Action设置Toast private Action1 mToastAction = new Action1() { @Override public void call(String s) { Toast.makeText(MoreActivity.this, s, Toast.LENGTH_SHORT).show(); } }; // 设置映射函数 private Func1, Observable> mOneLetterFunc = new Func1, Observable>() { @Override public Observable call(List strings) { return Observable.from(strings); // 映射字符串 } }; // 设置大写字母 private Func1 mUpperLetterFunc = new Func1() { @Override public String call(String s) { return s.toUpperCase(); // 大小字母 } }; // 连接字符串 private Func2 mMergeStringFunc = new Func2() { @Override public String call(String s, String s2) { return String.format("%s %s", s, s2); // 空格连接字符串 } }; // 创建字符串 private static String sayMyName() { return "Hello, I am your friend, Spike!"; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple); ButterKnife.bind(this); // 添加字符串, 省略Action的其他方法, 只使用一个onNext. Observable obShow = Observable.just(sayMyName()); // 先映射, 再设置TextView obShow.observeOn(AndroidSchedulers.mainThread()) .map(mUpperLetterFunc).subscribe(mTextViewAction); // 单独显示数组中的每个元素 Observable obMap = Observable.from(mManyWords); // 映射之后分发 obMap.observeOn(AndroidSchedulers.mainThread()) .map(mUpperLetterFunc).subscribe(mToastAction); // 优化过的代码, 直接获取数组, 再分发, 再合并, 再显示toast, Toast顺次执行. Observable.just(mManyWordList) .observeOn(AndroidSchedulers.mainThread()) .flatMap(mOneLetterFunc) .reduce(mMergeStringFunc) .subscribe(mToastAction); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/NetworkActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import butterknife.Bind; import butterknife.ButterKnife; import org.wangchenlong.testdetailrxandroid.networks.UserListAdapter; import org.wangchenlong.testdetailrxandroid.networks.NetworkWrapper; /** * Rx的网络请求方式 *

* Created by wangchenlong on 15/12/31. */ public class NetworkActivity extends Activity { @Bind(R.id.network_rv_list) RecyclerView mRvList; // 列表 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_network); ButterKnife.bind(this); // 设置Layout管理器 LinearLayoutManager layoutManager = new LinearLayoutManager(this); layoutManager.setOrientation(LinearLayoutManager.VERTICAL); mRvList.setLayoutManager(layoutManager); // 设置适配器 UserListAdapter adapter = new UserListAdapter(this::gotoDetailPage); NetworkWrapper.getUsersInto(adapter); // 加载网络信息 mRvList.setAdapter(adapter); } // 点击的回调 public interface UserClickCallback { void onItemClicked(String name); } // 跳转到库详情页面 private void gotoDetailPage(String name) { startActivity(NetworkDetailActivity.from(NetworkActivity.this, name)); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/NetworkDetailActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import butterknife.Bind; import butterknife.ButterKnife; import org.wangchenlong.testdetailrxandroid.networks.NetworkWrapper; import org.wangchenlong.testdetailrxandroid.networks.RepoListAdapter; /** * GitHub的库详细页面 *

* Created by wangchenlong on 15/12/31. */ public class NetworkDetailActivity extends Activity { private static final String USER_KEY = "network_detail_activity.user"; @Bind(R.id.network_rv_list) RecyclerView mRvList; public static Intent from(Context context, String username) { Intent intent = new Intent(context, NetworkDetailActivity.class); intent.putExtra(USER_KEY, username); return intent; } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_network); ButterKnife.bind(this); // 设置布局 LinearLayoutManager manager = new LinearLayoutManager(this); manager.setOrientation(LinearLayoutManager.VERTICAL); mRvList.setLayoutManager(manager); // 设置Adapter RepoListAdapter adapter = new RepoListAdapter(); NetworkWrapper.getReposInfo(getIntent().getStringExtra(USER_KEY), adapter); mRvList.setAdapter(adapter); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/SafeActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.os.Bundle; import android.util.Log; import android.widget.TextView; import com.trello.rxlifecycle.components.support.RxAppCompatActivity; import java.util.concurrent.TimeUnit; import butterknife.Bind; import butterknife.ButterKnife; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; /** * Rx的线程安全 *

* Created by wangchenlong on 15/12/31. */ public class SafeActivity extends RxAppCompatActivity { private static final String TAG = "DEBUG-WCL: " + SafeActivity.class.getSimpleName(); @Bind(R.id.simple_tv_text) TextView mTvText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple); ButterKnife.bind(this); Observable.interval(1, TimeUnit.SECONDS) .observeOn(AndroidSchedulers.mainThread()) .compose(bindToLifecycle()) // 管理生命周期, 防止内存泄露 .subscribe(this::showTime); } private void showTime(Long time) { mTvText.setText(String.valueOf("时间计数: " + time)); Log.d(TAG, "时间计数器: " + time); } @Override protected void onPause() { super.onPause(); Log.w(TAG, "页面关闭!"); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/SimpleActivity.java ================================================ package org.wangchenlong.testdetailrxandroid; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import android.widget.Toast; import butterknife.Bind; import butterknife.ButterKnife; import rx.Observable; import rx.Scheduler; import rx.Subscriber; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; /** * RxJava的基础讲解, 包含一个观察者(Observable), 两个订阅者(Subscriber). *

* Created by wangchenlong on 15/12/30. */ public class SimpleActivity extends Activity { @Bind(R.id.simple_tv_text) TextView mTvText; // 观察事件发生 private Observable.OnSubscribe mObservableAction = new Observable.OnSubscribe() { @Override public void call(Subscriber subscriber) { subscriber.onNext(sayMyName()); // 发送事件 subscriber.onCompleted(); // 完成事件 } }; // 订阅者, 接收字符串, 修改控件 private Subscriber mTextSubscriber = new Subscriber() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { mTvText.setText(s); // 设置文字 } }; // 订阅者, 接收字符串, 提示信息 private Subscriber mToastSubscriber = new Subscriber() { @Override public void onCompleted() { } @Override public void onError(Throwable e) { } @Override public void onNext(String s) { Toast.makeText(SimpleActivity.this, s, Toast.LENGTH_SHORT).show(); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_simple); ButterKnife.bind(this); // 注册观察活动 Observable observable = Observable.create(mObservableAction); // 分发订阅信息 observable.observeOn(AndroidSchedulers.mainThread()); // 主线程 observable.subscribe(mTextSubscriber); observable.subscribe(mToastSubscriber); } // 创建字符串 private String sayMyName() { return "Hello, I am your friend, Spike!"; } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/networks/GitHubService.java ================================================ package org.wangchenlong.testdetailrxandroid.networks; import retrofit.http.GET; import retrofit.http.Path; import rx.Observable; /** * GitHub的服务 *

* Created by wangchenlong on 15/12/31. */ public interface GitHubService { String ENDPOINT = "https://api.github.com"; @GET("/users/{user}") // 获取个人信息 Observable getUserData(@Path("user") String user); @GET("/users/{user}/repos") // 获取库, 获取的是数组 Observable getRepoData(@Path("user") String user); } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/networks/NetworkWrapper.java ================================================ package org.wangchenlong.testdetailrxandroid.networks; import rx.Observable; import rx.android.schedulers.AndroidSchedulers; import rx.schedulers.Schedulers; /** * 用户获取类 *

* Created by wangchenlong on 15/12/31. */ public class NetworkWrapper { private static final String[] mFamousUsers = {"SpikeKing", "JakeWharton", "rock3r", "Takhion", "dextorer", "Mariuxtheone"}; // 获取用户信息 public static void getUsersInto(final UserListAdapter adapter) { GitHubService gitHubService = ServiceFactory.createServiceFrom(GitHubService.class, GitHubService.ENDPOINT); Observable.from(mFamousUsers) .flatMap(gitHubService::getUserData) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(adapter::addUser); } // 获取库信息 public static void getReposInfo(final String username, final RepoListAdapter adapter) { GitHubService gitHubService = ServiceFactory.createServiceFrom(GitHubService.class, GitHubService.ENDPOINT); gitHubService.getRepoData(username) .flatMap(Observable::from) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(adapter::addRepo); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/networks/RepoListAdapter.java ================================================ package org.wangchenlong.testdetailrxandroid.networks; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import org.wangchenlong.testdetailrxandroid.R; import java.util.ArrayList; import butterknife.Bind; import butterknife.ButterKnife; /** * 库的适配器 *

* Created by wangchenlong on 15/12/31. */ public class RepoListAdapter extends RecyclerView.Adapter { private ArrayList mGitHubRepos; // 数据列表 public RepoListAdapter() { mGitHubRepos = new ArrayList<>(); } // 动态修改列表数据 public void addRepo(GitHubRepo gitHubRepo) { mGitHubRepos.add(gitHubRepo); notifyItemInserted(mGitHubRepos.size() - 1); // 更新数据 } @Override public RepoViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_network_repo, parent, false); return new RepoViewHolder(view); } @Override public void onBindViewHolder(RepoViewHolder holder, int position) { holder.bindTo(mGitHubRepos.get(position)); } @Override public int getItemCount() { return mGitHubRepos.size(); } public static class RepoViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.network_item_iv_repo_name) TextView mIvRepoName; @Bind(R.id.network_item_iv_repo_detail) TextView mIvRepoDetail; public RepoViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } public void bindTo(GitHubRepo gitHubRepo) { mIvRepoName.setText(gitHubRepo.name); mIvRepoDetail.setText( String.valueOf("description: " + gitHubRepo.description + ", language: " + gitHubRepo.language)); } } public static class GitHubRepo { public String name; // 库的名字 public String description; // 描述 public String language; // 语言 } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/networks/ServiceFactory.java ================================================ package org.wangchenlong.testdetailrxandroid.networks; import retrofit.GsonConverterFactory; import retrofit.Retrofit; import retrofit.RxJavaCallAdapterFactory; /** * 工厂模式 *

* Created by wangchenlong on 15/12/31. */ public class ServiceFactory { public static T createServiceFrom(final Class serviceClass, String endpoint) { Retrofit adapter = new Retrofit.Builder() .baseUrl(endpoint) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) // 添加Rx适配器 .addConverterFactory(GsonConverterFactory.create()) // 添加Gson转换器 .build(); return adapter.create(serviceClass); } } ================================================ FILE: app/src/main/java/org/wangchenlong/testdetailrxandroid/networks/UserListAdapter.java ================================================ package org.wangchenlong.testdetailrxandroid.networks; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import com.squareup.picasso.Picasso; import java.util.ArrayList; import java.util.List; import butterknife.Bind; import butterknife.ButterKnife; import org.wangchenlong.testdetailrxandroid.NetworkActivity; import org.wangchenlong.testdetailrxandroid.R; /** * 显示列表 *

* Created by wangchenlong on 15/12/31. */ public class UserListAdapter extends RecyclerView.Adapter { private List mUsers; // 用户名集合 private NetworkActivity.UserClickCallback mCallback; // 用户点击项的回调 public UserListAdapter(NetworkActivity.UserClickCallback callback) { mCallback = callback; mUsers = new ArrayList<>(); } public void addUser(GitHubUser user) { mUsers.add(user); // 添加数据 notifyItemInserted(mUsers.size() - 1); // 更新最后一位 } @Override public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View item = LayoutInflater.from(parent.getContext()) .inflate(R.layout.item_network_user, parent, false); return new UserViewHolder(item, mCallback); } @Override public void onBindViewHolder(UserViewHolder holder, int position) { holder.bindTo(mUsers.get(position)); } @Override public int getItemCount() { return mUsers.size(); } // Adapter的ViewHolder public static class UserViewHolder extends RecyclerView.ViewHolder { @Bind(R.id.network_item_iv_user_picture) ImageView mIvUserPicture; @Bind(R.id.network_item_tv_user_name) TextView mTvUserName; @Bind(R.id.network_item_tv_user_login) TextView mTvUserLogin; @Bind(R.id.network_item_tv_user_page) TextView mTvUserPage; public UserViewHolder(View itemView, NetworkActivity.UserClickCallback callback) { super(itemView); ButterKnife.bind(this, itemView); // 绑定点击事件 itemView.setOnClickListener(v -> callback.onItemClicked(mTvUserLogin.getText().toString())); } // 绑定数据 public void bindTo(GitHubUser user) { mTvUserName.setText(user.name); mTvUserLogin.setText(user.login); mTvUserPage.setText(user.repos_url); Picasso.with(mIvUserPicture.getContext()) .load(user.avatar_url) .placeholder(R.drawable.ic_person_black_24dp) .into(mIvUserPicture); } } // 用户类, 名称必须与Json解析相同 public static class GitHubUser { public String login; public String avatar_url; public String name; public String repos_url; } } ================================================ FILE: app/src/main/res/drawable/ic_person_black_24dp.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_binding.xml ================================================ ================================================ FILE: app/src/main/res/layout/activity_main.xml ================================================