Android - Backendless:点赞按钮问题

Android - Backendless: Issue with like button

来自后台支持论坛。 "This support forum is strictly for Backendless-related issues. Any general problems outside of our APIs and backend services are not covered by support. Please consider posting to whosebug.com and/or Android forums."马克皮勒。

所以我post在这里解决我的问题。 在 backendless 支持论坛上,我得到了一些宝贵的帮助来保存和检索关系,但现在我面临着另一个关于“赞”按钮的问题。 我正在开发一个社交应用程序,其中有 3 个按钮:喜欢评论分享。 Link 在我无尽的支持线程: http://support.backendless.com/topic/some-questions-regarding-data-loading-in-recyclerview-android 现在我正在尝试使“赞”按钮起作用,但我面临以下问题:

如果你看下面的代码和我的屏幕截图 attached 你可以看到有一个没有填充的心形按钮,这意味着我没有点击那个按钮 post。在 2 号处有另一个按钮已填充,我点击喜欢它,该应用程序将我添加到这样的用户列表中 post。

if (user.getObjectId().equals(userId)) {

holder.like.setBackgroundResource(R.drawable.ic_star_rate_on);

holder.like.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

showToast();

}

});

} else {

holder.like.setBackgroundResource(R.drawable.ic_star_rate_off);

//onclick in another function: setLike(holder.like,holder.likes,feeds);

}

但问题是点击空心是不起作用的。我尝试创建一个 toast 来检查点击是否有效,但 toast 没有显示。

但是如果我点击一个我喜欢的项目(心形图标填充),它会显示吐司,我会检查它是否听我的点击....

我尝试调试应用程序,但调试中没有显示任何内容window...一切似乎都很正常,但无法找出代码的问题所在。 我的适配器 class 如下:

public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedsHolder> {

private List<Feeds> list;

private Context context;

private static String TAG = "MainActivity";

public FeedAdapter(Context context, List<Feeds> list) {

this.context = context;

this.list = list;

}

@Override

public FeedsHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.feed_item, parent, false);

return new FeedsHolder(view);

}

@Override

public void onBindViewHolder(final FeedsHolder holder, int position) {

//Starting Feeds

final Feeds feeds = list.get(position);

//Name

holder.name.setText(feeds.getOwner());

//Profile picture

holder.profilePictureURL = feeds.getProfilePictureURL();

//Image

holder.imageURL = feeds.getImageUrl();

//Getting date

Date myD = feeds.getCreated();

long ddate = myD.getTime();

String myDate = String.valueOf(DateUtils.getRelativeTimeSpanString(ddate, System.currentTimeMillis(), DateUtils.SECOND_IN_MILLIS));

holder.timeAgo.setText("• " + myDate);

//Get total likes

final int i = feeds.getLikes();

//Query

QueryOptions options = new QueryOptions();

options.setRelated( Arrays.asList( "usersThatLike" ) );

BackendlessDataQuery query = new BackendlessDataQuery();

query.setQueryOptions( options );

// getting all saved feeds with related users

Backendless.Data.of(Feeds.class).find(query, new AsyncCallback<BackendlessCollection<Feeds>>() {

@Override

public void handleResponse(BackendlessCollection<Feeds> response) {

String userId = Backendless.UserService.CurrentUser().getObjectId();

for (Feeds feed: response.getCurrentPage()) {

List<BackendlessUser> likedUsers = feeds.getUsersThatLike();

for (BackendlessUser user : likedUsers)

if (user.getObjectId().equals(userId)) {

Log.d(TAG, "No -------------------------------------");

holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_on));

holder.like.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Toast.makeText(context, "You already like this item", Toast.LENGTH_SHORT).show();

}

});

} else {

holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_off));

holder.like.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View v) {

Log.d(TAG, "It should work +++++++++++++++++++++++++++++++");

// getting current user

Toast.makeText(context, "Arrived", Toast.LENGTH_SHORT).show();

BackendlessUser currentUser = Backendless.UserService.CurrentUser();

// adding current user as one who "liked" feed, you should implement "adding" by yourself

List<BackendlessUser> list = new ArrayList<>();

list.add(currentUser);

feeds.setUsersThatLike(list);

holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_on));

feeds.setLikes(i + 1);

Backendless.Data.of(Feeds.class).save(feeds, new AsyncCallback<Feeds>() {

@Override

public void handleResponse(Feeds feeds) {

int likes = feeds.getLikes();

if (likes == 1) {

holder.likes.setText(i + 1 + " like");

} else {

holder.likes.setText(i + 1 + " likes");

}

}

@Override

public void handleFault(BackendlessFault backendlessFault) {

}

});

}

});

}

}

}

@Override

public void handleFault(BackendlessFault backendlessFault) {

}

});

holder.status.setText(feeds.getStatus());

String thisString = "no";

String myImageString = "no";

Picasso.with(context).load(holder.profilePictureURL).placeholder(R.drawable.placeholder).into(holder.profilePicture);

String image = feeds.getIsImageUrlEmpty();

if (!image.equals(myImageString)) {

holder.image.setVisibility(View.GONE);

holder.tagStatusBottom.setVisibility(View.VISIBLE);

holder.tagImageBottom.setVisibility(View.GONE);

} else {

holder.image.setVisibility(View.VISIBLE);

holder.tagStatusBottom.setVisibility(View.GONE);

holder.tagImageBottom.setVisibility(View.VISIBLE);

Picasso.with(context).load(holder.imageURL).placeholder(R.drawable.placeholder).into(holder.image);

}

String myString = feeds.getIsTagEmpty();

if (myString.equals(thisString)){

holder.tagImageBottom.setVisibility(View.VISIBLE);

if (!image.equals(myImageString)) {

holder.image.setVisibility(View.GONE);

holder.tagStatusBottom.setVisibility(View.VISIBLE);

holder.tagImageBottom.setVisibility(View.GONE);

} else {

holder.image.setVisibility(View.VISIBLE);

holder.tagStatusBottom.setVisibility(View.GONE);

holder.tagImageBottom.setVisibility(View.VISIBLE);

Picasso.with(context).load(holder.imageURL).placeholder(R.drawable.placeholder).into(holder.image);

}

} else {

holder.tagImageBottom.setVisibility(View.GONE);

holder.tagStatusBottom.setVisibility(View.GONE);

}

String str = feeds.getTag();

ArrayList<int[]> hashtagSpans1 = getSpans(str, '#');

SpannableString commentsContent1 =

new SpannableString(str);

setSpanComment(commentsContent1, hashtagSpans1) ;

holder.tagImageBottom.setText(commentsContent1);

holder.tagStatusBottom.setText(commentsContent1);

holder.tagImageBottom.setMovementMethod(LinkMovementMethod.getInstance());

int likes = feeds.getLikes();

if (likes == 1) {

holder.likes.setText(i +" like");

} else {

holder.likes.setText(i +" likes");

}

}

public ArrayList<int[]> getSpans(String body, char prefix) {

ArrayList<int[]> spans = new ArrayList<int[]>();

Pattern pattern = Pattern.compile(prefix + "\w+");

Matcher matcher = pattern.matcher(body);

// Check all occurrences

while (matcher.find()) {

int[] currentSpan = new int[2];

currentSpan[0] = matcher.start();

currentSpan[1] = matcher.end();

spans.add(currentSpan);

}

return spans;

}

private void setSpanComment(SpannableString commentsContent, ArrayList<int[]> hashtagSpans) {

for(int i = 0; i < hashtagSpans.size(); i++) {

int[] span = hashtagSpans.get(i);

int hashTagStart = span[0];

int hashTagEnd = span[1];

commentsContent.setSpan(new Hashtag(context),

hashTagStart,

hashTagEnd, 0);

}

}

@Override

public int getItemCount() {

return list.size();

}

这是我的 Feed class:

public class Feeds

{

private String owner;

private String tag;

private String profilePictureURL;

private String imageURL;

private Date created;

private Date updated;

private String status;

private int likes;

private String isTagEmpty;

private String isImageUrlEmpty;

private List<BackendlessUser> usersThatLike;

public String getOwner()

{

return owner;

}

public void setOwner( String owner )

{

this.owner = owner;

}

public int getLikes()

{

return likes;

}

public void setLikes ( int likes )

{

this.likes = likes;

}

public String getIsTagEmpty()

{

return isTagEmpty;

}

public void setIsTagEmpty ( String isTagEmpty )

{

this.isTagEmpty = isTagEmpty;

}

public String getIsImageUrlEmpty()

{

return isImageUrlEmpty;

}

public void setIsImageUrlEmpty ( String isImageUrlEmpty )

{

this.isImageUrlEmpty = isImageUrlEmpty;

}

public String getStatus()

{

return status;

}

public void setStatus( String status )

{

this.status = status;

}

public String getTag()

{

return tag;

}

public void setTag( String tag )

{

this.tag = tag;

}

public String getProfilePictureURL()

{

return profilePictureURL;

}

public void setProfilePictureURL ( String profilePictureURL )

{

this.profilePictureURL = profilePictureURL;

}

public String getImageUrl()

{

return imageURL;

}

public void setImageUrl ( String imageURL )

{

this.imageURL = imageURL;

}

public Date getCreated()

{

return created;

}

public Date getUpdated()

{

return updated;

}

public List<BackendlessUser> getUsersThatLike() {

return usersThatLike;

}

public void setUsersThatLike(List<BackendlessUser> usersThatLike) {

this.usersThatLike = usersThatLike;

}

}

你能帮我吗?

编辑: 在下面的答案中实施代码后,它不起作用。这就是我编辑代码的方式:

    //Skipped previous code. Posted only the changed code
Backendless.Data.of(Feeds.class).find(query, new AsyncCallback<BackendlessCollection<Feeds>>() {
                @Override
                public void handleResponse(final BackendlessCollection<Feeds> feedsBackendlessCollection) {

//Suggested by sihao
                    holder.like.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            String userId = Backendless.UserService.CurrentUser().getObjectId();

                            for (Feeds feed: feedsBackendlessCollection.getCurrentPage()) {

                                List<BackendlessUser> likedUsers = feeds.getUsersThatLike();

                                for (BackendlessUser user : likedUsers)

                                    if (user.getObjectId().equals(userId)) {

                                        Toast.makeText(context,"You already liked this item",Toast.LENGTH_SHORT).show();
                                    } else {
                                        // getting current user

                                        BackendlessUser currentUser = Backendless.UserService.CurrentUser();

    // adding current user as one who "liked" feed, you should implement "adding" by yourself

                                        List<BackendlessUser> list = new ArrayList<>();

                                        list.add(currentUser);

                                        feeds.setUsersThatLike(list);

                                        holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_on));

                                        feeds.setLikes(i + 1);

                                        Backendless.Data.of(Feeds.class).save(feeds, new AsyncCallback<Feeds>() {
                                            @Override
                                            public void handleResponse(Feeds feeds) {
                                                int likes = feeds.getLikes();

                                                if (likes == 1) {

                                                    holder.likes.setText(i + 1 + " like");

                                                } else {

                                                    holder.likes.setText(i + 1 + " likes");

                                                }
                                            }

                                            @Override
                                            public void handleFault(BackendlessFault backendlessFault) {

                                            }
                                        });
                                    }
                            }
                        }
                    });
                }

                @Override
                public void handleFault(BackendlessFault backendlessFault) {

                }
            });

更新: 这些天我试图解决这个问题并得到了一个(不错的)想法。 我成功地将按钮背景从空心更改为充满用户喜欢的元素的心。我有以下想法:检查心脏是空的还是充满的。因此,在 activity 加载时,我的应用程序从 "usersThatLike" 列获取数据,如果用户出现在后端列表中,则设置填充心形可绘制对象,如果不存在,则设置空心可绘制对象。 所以现在我正在尝试对可绘制对象进行检查。 如果心已满而不是祝酒词 "You liked this item already" 否则将喜欢添加到项目并将用户添加到当前项目的 "usersThatLike" 列。 但它会为所有项目返回 "filled" 心。我的意思是说,即使心脏可绘制对象是空的,它也会返回它已填充,如果我单击填充的心脏可绘制对象,它会显示吐司,但如果心脏未填充,它将显示相同的吐司: 我的代码是:

//*** Skipped the query code. In handleResponse:
    String userId = Backendless.UserService.CurrentUser().getObjectId();
                    for (Feeds feed: response.getData()) {
                        feed = list.get(position);

                        List<BackendlessUser> likedUsers = feed.getUsersThatLike();

                        for (BackendlessUser user : likedUsers)
                            if (user.getObjectId().equals(userId)) {
                                holder.like.setBackgroundResource(R.drawable.ic_star_rate_on);
                            } else if (!user.getObjectId().equals(userId)) {
                                holder.like.setBackgroundResource(R.drawable.ic_star_rate_off);
                            }
                    }

在 handleResponse 之外,在查询代码之后的正常 onBindViewHolder 中,我正在检查可绘制对象,如下所示:

//***HERE IS THE QUERY
    Backendless.Data.of(Feeds.class).find(query, new AsyncCallback<BackendlessCollection<Feeds>>() {

            //***SKIPPED FOR BREVITY 

        });

//***HERE IS THE CHECK

        holder.like.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (holder.like.getBackground() != context.getDrawable(R.drawable.ic_star_rate_off)){
                toast();
            } else {
                setLike();
            }
        }
    });

我相信你的问题出在这里。

参考你上面给出的代码:

//****PART I: NOTICE HERE****//
if (user.getObjectId().equals(userId)) {

     holder.like.setBackgroundResource(R.drawable.ic_star_rate_on);

     //****YOUR CLICK LISTENER*****//
     holder.like.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             showToast();
          }

      });

  //****PART II: NOTICE HERE****//
 } else {

  holder.like.setBackgroundResource(R.drawable.ic_star_rate_off);

  //onclick in another function: setLike(holder.like,holder.likes,feeds);

}

如果您查看第一部分和第二部分所示的两个部分,您会发现如果用户之前喜欢 post,您只会附加按钮的 ClickListener。

您的解决方案是将此 ClickListener 移出范围,移至更一般的位置。

例如:

//****YOUR CLICK LISTENER*****//
holder.like.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       showToast();
   }

});

//****PART I: NOTICE HERE****//
if (user.getObjectId().equals(userId)) {

     holder.like.setBackgroundResource(R.drawable.ic_star_rate_on);

  //****PART II: NOTICE HERE****//
 } else {

  holder.like.setBackgroundResource(R.drawable.ic_star_rate_off);

  //onclick in another function: setLike(holder.like,holder.likes,feeds);

}

编辑:

从您的代码来看,您似乎试图将两个 ClickListener 附加到同一个按钮。

您应该尝试这种方法,而不是那样做。

  • 首先,使用我提供的修改示例。 (添加通用点击监听器)

  • 在您的 ClickListener 中,以这种方式实现它。

     //****YOUR CLICK LISTENER*****//
     holder.like.setOnClickListener(new View.OnClickListener() {
         @Override
         public void onClick(View v) {
             if (user.getObjectId().equals(userId)) {
                 .... do your stuff here
             } else {
                 .... do other stuff here
             }
          }
    
      });
    

更新:

大家好, 我终于找到了一个非常棘手的解决方案来解决我的问题。 我能够将用户保存到 "usersThatLike" 列并在特定项目上设置类似。但是每次我点击喜欢按钮时,它都会显示祝酒词 "You already liked it",只有当我出现在 usersThatLike 列表中时才应该显示,所以出现了问题。 我使用以下技巧来解决这个问题: 在我的 RecyclerView 适配器中,我这样查询 class:

QueryOptions options = new QueryOptions();

    options.setRelated( Arrays.asList( "usersThatLike" ) );

    BackendlessDataQuery query = new BackendlessDataQuery();

    query.setQueryOptions( options );

    Backendless.Data.of(Feeds.class).find(query, new AsyncCallback<BackendlessCollection<Feeds>>() {

        @Override

        public void handleResponse(BackendlessCollection<Feeds> response) {
            String userId = Backendless.UserService.CurrentUser().getObjectId();
            for (Feeds feed: response.getData()) {
                feed = list.get(position);

                List<BackendlessUser> likedUsers = feed.getUsersThatLike();

                for (BackendlessUser user : likedUsers)
                    if (user.getObjectId().equals(userId)) {
                        holder.like.setBackgroundResource(R.drawable.ic_star_rate_on);
                    } else if (!user.getObjectId().equals(userId)) {
                        holder.like.setBackgroundResource(R.drawable.ic_star_rate_off);
                    }
            }

        }

        @Override

        public void handleFault(BackendlessFault backendlessFault) {

        }

    });

如您所见,如果查询 returns 用户不在列表中,我将 drawable 设置为关闭,如果用户在列表中,则打开。

所以这就是我解决问题的方法。 在我的查询之外,我创建了以下检查:

holder.likeLayout.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (holder.like.getBackground().getConstantState() != ContextCompat.getDrawable(context, R.drawable.ic_star_rate_off).getConstantState()){
                toast();
            } else {
                setLike();
            }
        }
    });

在上面的代码中,我获取了按钮背景,并将其与我的可绘制文件夹中的图片进行比较,星号已关闭。 如果点赞按钮带有 star_off,它将设置点赞并将用户添加到 usersThatLike 列表。否则敬酒:"You already liked this item"

希望它可以帮助其他人并节省他们的时间,因为我在这个问题上花了很多时间。

此致


旧答案:

回复sihao的评论: @sihao 如果你检查我的第一个 post 你会看到:

    if (user.getObjectId().equals(userId)) {

    Log.d(TAG, "No -------------------------------------");

    holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_on));

// FIRST ONCLICK LISTENER
    holder.like.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    Toast.makeText(context, "You already like this item", Toast.LENGTH_SHORT).show();

    }

    });

    } else {

    holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_off));

// SECOND ONCLICK LISTENER
    holder.like.setOnClickListener(new View.OnClickListener() {

    @Override

    public void onClick(View v) {

    Log.d(TAG, "It should work +++++++++++++++++++++++++++++++");

    // getting current user

    Toast.makeText(context, "Arrived", Toast.LENGTH_SHORT).show();

    BackendlessUser currentUser = Backendless.UserService.CurrentUser();

    // adding current user as one who "liked" feed, you should implement "adding" by yourself

    List<BackendlessUser> list = new ArrayList<>();

    list.add(currentUser);

    feeds.setUsersThatLike(list);

    holder.like.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.ic_star_rate_on));

    feeds.setLikes(i + 1);

    Backendless.Data.of(Feeds.class).save(feeds, new AsyncCallback<Feeds>() {

    @Override

    public void handleResponse(Feeds feeds) {

    int likes = feeds.getLikes();

    if (likes == 1) {

    holder.likes.setText(i + 1 + " like");

    } else {

    holder.likes.setText(i + 1 + " likes");

    }

    }

    @Override

    public void handleFault(BackendlessFault backendlessFault) {

    }

    });

    }

    });