之前我们一般是在适配器中做点击事件,但是我们使用DataBinding
之后,我们就可以直接在xml
中实现.我们之前说过xml
中是可以写点击事件的,它接受的是一个lambda
表达式,表达式里面是一个类点静态方法,如:
android:onClick="@{()->InterActionPresenter.toggleFeedDiss(lifeCycleOwner,feed)}"
我们就新建一个类InterActionPresenter
,里面有我们的点赞和踩对应的方法
public class InterActionPresenter {
private static final String URL_TOGGLE_FEED_LIK = "/ugc/toggleFeedLike";
private static final String URL_TOGGLE_FEED_DISS = "/ugc/dissFeed";
/**
* 给一个帖子点赞/取消点赞,它和给帖子点踩一踩是互斥的
*/
public static void toggleFeedLike(LifecycleOwner owner, Feed feed) {
if (!UserManager.get().isLogin()) {
LiveData<User> loginLiveData = UserManager.get().login(AppGlobals.getApplication());
loginLiveData.observe(owner, new Observer<User>() {
@Override
public void onChanged(User user) {
if (user != null) {
toggleFeedLikeInternal(feed);
}
loginLiveData.removeObserver(this);
}
});
return;
}
toggleFeedLikeInternal(feed);
}
private static void toggleFeedLikeInternal(Feed feed) {
ApiService.get(URL_TOGGLE_FEED_LIK)
.addParam("userId", UserManager.get().getUserId())
.addParam("itemId", feed.itemId)
.execute(new JsonCallback<JSONObject>() {
@Override
public void onSuccess(ApiResponse<JSONObject> response) {
if (response.body != null) {
boolean hasLiked = response.body.getBoolean("hasLiked").booleanValue();
feed.getUgc().setHasLiked(hasLiked);
}
}
@Override
public void onError(ApiResponse<JSONObject> response) {
showToast(response.message);
}
});
}
/**
* 给一个帖子点踩一踩/取消踩一踩,它和给帖子点赞是互斥的
*/
public static void toggleFeedDiss(LifecycleOwner owner, Feed feed) {
if (!UserManager.get().isLogin()) {
LiveData<User> loginLiveData = UserManager.get().login(AppGlobals.getApplication());
loginLiveData.observe(owner, new Observer<User>() {
@Override
public void onChanged(User user) {
if (user != null) {
toggleFeedDissInternal(feed);
}
loginLiveData.removeObserver(this);
}
});
return;
}
toggleFeedDissInternal(feed);
}
private static void toggleFeedDissInternal(Feed feed) {
ApiService.get(URL_TOGGLE_FEED_DISS).addParam("userId", UserManager.get().getUserId())
.addParam("itemId", feed.itemId)
.execute(new JsonCallback<JSONObject>() {
@Override
public void onSuccess(ApiResponse<JSONObject> response) {
if (response.body != null) {
boolean hasLiked = response.body.getBoolean("hasLiked").booleanValue();
feed.getUgc().setHasdiss(hasLiked);
}
}
@Override
public void onError(ApiResponse<JSONObject> response) {
showToast(response.message);
}
});
}
private static void showToast(String message) {
ArchTaskExecutor.getMainThreadExecutor().execute(new Runnable() {
@Override
public void run() {
Toast.makeText(AppGlobals.getApplication(), message, Toast.LENGTH_SHORT).show();
}
});
}
}
简单解释下,不管是点赞还是踩,我们都需要用户登录,我们判断用户等没登录用的UserManager
这个类,这个类我们上一篇在QQ
登录的时候用过,如果用户没有登录,我们就需要跳转到我们的登录页
当我们请求完成回来之后,我们需要将我们的按钮文本进行改变,这时候我们就需要改变Feed
对象里面的Ugc
对象相应的属性,这个时候就需要我们的Ugc
对象继承自BaseObservable
,我们改变的是
这两个属性,所以我们需要添加他们的get/set
方法,同时在get
方法上面加上@Bindable
注解,在set
方法中调用notifyPropertyChanged
这个方法
@Bindable
public boolean isHasLiked() {
return hasLiked;
}
public void setHasLiked(boolean hasLiked) {
if (this.hasLiked == hasLiked)
return;
if (hasLiked) {
likeCount = likeCount + 1;
setHasdiss(false);
} else {
likeCount = likeCount - 1;
}
this.hasLiked = hasLiked;
notifyPropertyChanged(BR._all);
}
@Bindable
public boolean isHasdiss() {
return hasdiss;
}
public void setHasdiss(boolean hasdiss) {
if (this.hasdiss == hasdiss)
return;
if (hasdiss) {
setHasLiked(false);
}
this.hasdiss = hasdiss;
notifyPropertyChanged(BR._all);
}
这个notifyPropertyChanged
方法我们需要传一个fieldid
,我们可以通过BR
来点出来
这些字段都是哪来的呢?就是我们在xml
中声明的变量,类似这种
我们没声明一个variable
,databinding
编译的时候都会生成一个引用,因为我们要改变的ugc
是在Feed
中,我们可以用BR.feed
也可以用BR._all
,这个notifyPropertyChanged
就是告诉观察者,我这里有属性改变了,需要重新执行数据绑定,我们简单看下怎么回事,我们以LayoutFeedAuthorBindingImpl
这个类为例,这个类是自动生成的
它里面有个setuser
方法
这里面就会执行notifyPropertyChanged
方法,最后会调用requestRebind
这个方法,我们继续往下看,最终会执行
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
java.lang.String userName = null;
java.lang.String userAvatar = null;
com.mooc.ppjoke.model.User user = mUser;
if ((dirtyFlags & 0x3L) != 0) {
if (user != null) {
// read user.name
userName = user.name;
// read user.avatar
userAvatar = user.avatar;
}
}
// batch finished
if ((dirtyFlags & 0x3L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.authorName, userName);
com.mooc.libcommon.view.PPImageView.setImageUrl(this.avatar, userAvatar, true, (int)0);
}
}
这里我们看见有setText
和setImageUrl
方法,setImageUrl
我们知道,这个是我们自己写的方法,我们点进去setText
,
@BindingAdapter("android:text")
public static void setText(TextView view, CharSequence text) {
final CharSequence oldText = view.getText();
if (text == oldText || (text == null && oldText.length() == 0)) {
return;
}
if (text instanceof Spanned) {
if (text.equals(oldText)) {
return; // No change in the spans, so don't set anything.
}
} else if (!haveContentsChanged(text, oldText)) {
return; // No content changes, so don't set anything.
}
view.setText(text);
}
这个个静态方法,同时会判断是否改变,改变之后重新调用TextView
的setText
方法进行赋值
OK,我们简单分析完之后,回到我们的xml
中,我们写下点击事件
<com.google.android.material.button.MaterialButton
android:id="@+id/like"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="@{()->InterActionPresenter.toggleFeedLike(lifeCycleOwner,feed)}"
android:text="@{feed.ugc.likeCount>0?StringConvert.convertFeedUgc(feed.ugc.likeCount):@string/like}"
android:textColor="@{feed.ugc.hasLiked?@color/color_theme:@color/color_3d3}"
android:textSize="@dimen/sp_14"
app:backgroundTint="@color/color_white"
app:cornerRadius="0dp"
app:icon="@{feed.ugc.hasLiked?@drawable/icon_cell_liked:@drawable/icon_cell_like}"
app:iconGravity="textStart"
app:iconPadding="4dp"
app:iconTint="@{feed.ugc.hasLiked?@color/color_theme:@color/color_3d3}"
tools:icon="@drawable/icon_cell_like"
tools:iconTint="@color/color_3d3"
tools:text="1000"
tools:textColor="@color/color_3d3" />
<com.google.android.material.button.MaterialButton
android:id="@+id/diss"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:onClick="@{()->InterActionPresenter.toggleFeedDiss(lifeCycleOwner,feed)}"
android:text="踩"
android:textColor="@{feed.ugc.hasdiss?@color/color_theme:@color/color_3d3}"
android:textSize="@dimen/sp_14"
app:backgroundTint="@color/color_white"
app:cornerRadius="0dp"
app:icon="@{feed.ugc.hasdiss?@drawable/icon_cell_dissed:@drawable/icon_cell_diss}"
app:iconGravity="textStart"
app:iconPadding="4dp"
app:iconTint="@{feed.ugc.hasdiss?@color/color_theme:@color/color_3d3}"
tools:icon="@drawable/icon_cell_diss"
tools:iconTint="@color/color_3d3"
tools:text="1000"
tools:textColor="@color/color_3d3" />
这里的lifeCycleOwner
和feed
一样,我们在上面声明的
<variable
name="feed"
type="com.mooc.ppjoke.model.Feed" />
<variable
name="lifeCycleOwner"
type="androidx.lifecycle.LifecycleOwner" />
<import type="com.mooc.ppjoke.model.Feed" />
<import type="com.mooc.ppjoke.utils.StringConvert" />
<import type="android.content.Context" />
<import type="com.mooc.ppjoke.ui.home.InterActionPresenter" />
OK,我们看下效果