【问题标题】:Android - Backendless: Issue with like buttonAndroid - Backendless:喜欢按钮的问题
【发布时间】:2016-07-31 16:14:43
【问题描述】:

来自后端支持论坛。 “此支持论坛仅针对与 Backendless 相关的问题。我们的 API 和后端服务之外的任何一般问题均不在支持范围内。请考虑发布到 stackoverflow.com 和/或 Android 论坛。”马克·皮勒。

所以我在这里发布我的问题。 在后端支持论坛上,我得到了一些宝贵的帮助来保存和检索关系,但现在我面临着“赞”按钮的另一个问题。 我正在开发一个社交应用程序,其中有 3 个按钮:Like Comment Share。 链接在我的后端支持线程: http://support.backendless.com/topic/some-questions-regarding-data-loading-in-recyclerview-android 现在我正在尝试让 Like 按钮工作,但我面临以下问题:

如果您查看以下代码和屏幕截图 I attached,您可以看到没有填充的“点赞”心形按钮,这意味着我没有为该帖子点赞。在 2 号处,还有另一个按钮被填满,我点赞了它,应用程序将我添加到了喜欢该帖子的用户列表中。

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 没有出现。

但是,如果我单击我喜欢的项目(填充心形图标),它会向我显示我放置的 toast,以检查它是否听取了我的点击...。

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

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 类:

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) {

                }
            });

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

//*** 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);
                            }
                    }

在查询代码之后,在正常的 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();
            }
        }
    });

【问题讨论】:

    标签: android backendless


    【解决方案1】:

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

    参考上面给出的代码:

    //****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);
    
    }
    

    如果您查看第 I 部分和第 II 部分所示的两个部分,您会发现如果用户之前喜欢过该帖子,您只会附加按钮的 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 列中,那么喜欢按钮被禁用。否则它是活动的。我试图将两个 onClicks 都排除在外,但这似乎并不能解决问题。顺便说一句,您从检查中提取的点击侦听器在没有您的 mod 的情况下工作,即使它在检查块中,它也会显示吐司,所以那里没有问题。这是第二个点击监听器: setLike(holder.like,holder.likes,feeds);这是行不通的。如果用户列在列表中,我可以看到 toast,但如果不是,则单击侦听器不会执行任何操作...
    • 这正是我在说的,请尝试理解代码在做什么
    • "如果用户列在列表中,我可以看到 toast,但如果不是,则单击侦听器不会做任何事情"是因为您仅在以下情况下绑定单击侦听器该用户被列出,否则您的点击侦听器未附加。因此没有结果。
    • 你是说这条线? //onclick 在另一个函数中: setLike(holder.like,holder.likes,feeds);
    • 确实如此,但请检查我的答案,onclick 侦听器在检查的 else 语句中的位置
    【解决方案2】:

    更新:

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

    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) {
    
            }
    
        });
    

    如您所见,如果查询返回该用户不在列表中,则我将带有星号的可绘制对象设置为关闭,如果该用户在列表中,则打开。

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

    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();
                }
            }
        });
    

    在上面的代码中,我得到了按钮背景,并将其与我的可绘制文件夹中的图像进行比较,并关闭星号。 如果like按钮带有star_off,它将设置like并将用户添加到usersThatLike列表。否则显示敬酒:“你已经喜欢这个项目”

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

    问候


    旧答案:

    回复思豪的评论: @sihao 如果你查看我的第一篇文章,你会看到:

        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) {
    
        }
    
        });
    
        }
    
        });
    

    【讨论】:

    • 您应该对您的问题进行编辑,而不是发布答案并发表评论以通知我们您希望我们查看编辑内容
    • 我想我知道你的意思,让我看看能不能帮上忙。我会修改我的答案
    • 抱歉,我的问题已经包含了那部分代码。我刚刚从我的问题中复制了我的答案中的代码。
    • 对此我深表歉意。下次会记住的。下次会编辑我的问题。再次抱歉
    • 不用担心,我只是说如果它遵循 SO 的工作方式,其他有类似问题的用户将能够理解您的问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    相关资源
    最近更新 更多