1.关于DataBinding
1.1 RecyclerView中使用DataBinding
public class FavorAdapter extends RecyclerView.Adapter<FavorAdapter.ViewHolder> {
...
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_list_item_cover, parent, false);
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
final MyFavor myFavor = mMyFavors.get(position);
holder.bind(myFavor);
...
}
class ViewHolder extends RecyclerView.ViewHolder {
HomeListItemCoverBinding mBinding;
public ViewHolder(View itemView) {
super(itemView);
mBinding = DataBindingUtil.bind(itemView);
}
public void bind(@NonNull MyFavor favor) {
mBinding.setFavor(favor);
}
}
}
其中要注意的一点是HomeListItemCoverBinding mBinding;
的位置,最开始的时候图方便,把它直接放到Adapter里面,然后在onBindViewHolder(final ViewHolder holder, int position)
里直接使用了,这样是不行的。因为每一个Binding对应了一个Item(ViewHolder),所以不能把它放到Adapter下面,这样的话刷新界面或者移动列表会出现数据错误。另外想要在onBindViewHolder(final ViewHolder holder, int position)
方法里获取binding的话就用holder.mBinding来操作。
1.2 关于绑定String类型数据
比如一个登陆页面
<layout>
<data>
<variable name="username" type="String"/>
<variable name="password" type="String"/>
</data>
...
...
...
</layout>
这里的
<variable name="username" type="String"/>
<variable name="password" type="String"/>
如果1.绑定对象是EditText 2.双向绑定,那么不能使用String类型。由于String是其实是一个不变类,一旦在输入框中改变的文字,那么Java代码中绑定的String就已经不是输入框里的那个String了。要为View指定一个ViewModel
public class LoginViewModel {
private String mUsername;
private String mPassword;
public LoginViewModel(String username, String password) {
mUsername = username;
mPassword = password;
}
getters...
setters...
然后把要绑定的属性放进去。
<variable
name="loginViewModel"
type="com.yohom.show.launcher.view.viewmodel.LoginViewModel"/>
2.关于Retrofit请求
presenter层
public class PopularPresenter extends BasePresenter<HomeRepo, PopularContract.View> implements PopularContract.Presenter {
@Inject
protected PopularPresenter(HomeRepo homeRepo, BaseScheduler scheduler) {
super(homeRepo, scheduler);
}
@Override
public void getPopularList(String page) {
Subscription subscription = mRepo
.getPopular(page)
.subscribeOn(mScheduler.io())
.observeOn(mScheduler.ui())
.subscribe(new MyObserver<Bean<Popular>>(){
@Override
public void onNext(Bean<Popular> bean) {
mView.processPopular(bean);
}
});
mSubscriptions.add(subscription);
}
}
model层
public class HomeRepo {
private HomeService mService;
public HomeRepo() {
mService = getRetrofit().create(HomeService.class);
}
public Observable<Bean<List<MyFavor>>> getFavouriteList() {
MyParams params = new MyParams();
return mService.getFavouriteList(params.get());
}
interface HomeService {
@FormUrlEncoded
@POST(NEW_ATTENTION)
Observable<Bean<List<MyFavor>>> getFavouriteList(@FieldMap Map<String, String> map);
}
}
刚开始只写了presenter的时候,想先测试一下能不能正确返回数据并解析成对应的实体类,后来发现retrofit请求怎么也发不出去,但是其他presenter的请求却能发出去,一开始还以为有可能是连续两个请求间隔太短了,debug了半天,后来发现是因为
@Override
public void getPopularList(String page) {
Subscription subscription = mRepo
.getPopular(page)
.subscribeOn(mScheduler.io())
.observeOn(mScheduler.ui())
.subscribe(new MyObserver<Bean<Popular>>(){
@Override
public void onNext(Bean<Popular> bean) {
mView.processPopular(bean);
}
});
mSubscriptions.add(subscription);
}
写成了
@Override
public void getPopularList(String page) {
mRepo.getPopular(page);
}
我以为只要调用了HomeService的getPopular方法就会发起请求,原来是一定要订阅了才会发起请求(至少只有订阅了才会打印日志),谨记谨记。
3.在xml文件中指定RecyclerView的LayoutManager
<RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="GridLayoutManager"
app:spanCount="2"/>
重点是
app:layoutManager="GridLayoutManager"
app:spanCount="2"
这两句,其他的属性以此类推。
4.图片加边框
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke android:width="3dp" android:color="@color/gray" />
<padding android:left="1dp" android:top="1dp"
android:right="1dp" android:bottom="1dp" />
</shape>
重点是这个padding属性,不加的话边框是看不出的。