对象动画师不删除更新监听器android

2024-04-23

美好的一天。我有一个场景,这个半正常的对象动画师不断地反复触发,导致堆增长,当然在某些时候还会出现内存不足问题。这是如何进行的。我为这样的彩虹动画制作了静态方法。

  public static ObjectAnimator startRainbowAnimation(Context context,
                                                   String textToShow,
                                                   final TextView textViewToAttach) {
    AnimatedColorSpan span = new AnimatedColorSpan(context);
    final SpannableString spannableString = new SpannableString(textToShow);
    String substring = textToShow;
    int start = textToShow.indexOf(substring);
    int end = start + substring.length();
    spannableString.setSpan(span, start, end, 0);

    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(
            span, ANIMATED_COLOR_SPAN_FLOAT_PROPERTY, 0, 100);
    objectAnimator.setEvaluator(new FloatEvaluator());
    objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            System.gc();
            Log.d("Fafasfasfas", "onAnimationUpdate: inside true");
            textViewToAttach.setText(spannableString);
        }
    });
    objectAnimator.setInterpolator(new LinearInterpolator());
    objectAnimator.setDuration(DURATION);
    objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
    objectAnimator.start();
    return objectAnimator;
}

private static final Property<AnimatedColorSpan, Float> ANIMATED_COLOR_SPAN_FLOAT_PROPERTY
        = new Property<AnimatedColorSpan, Float>(Float.class, "ANIMATED_COLOR_SPAN_FLOAT_PROPERTY") {
    @Override
    public void set(AnimatedColorSpan span, Float value) {
        span.setTranslateXPercentage(value);
    }

    @Override
    public Float get(AnimatedColorSpan span) {
        return span.getTranslateXPercentage();
    }
};

我在 recyclerview 适配器中这样调用这个方法

 @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        ChatModel chatModel = chatModelList.get(position);

        System.gc();

        String messageBody = chatModel.getMessage().replaceAll("userid=" + chatModel.getUserId() + ":" + Constants.TYPE_MESSAGE_ATTACHMENT, "").replaceAll("userid=" + chatModel.getOpponentId() + ":" + Constants.TYPE_MESSAGE_ATTACHMENT, "");
        holder.message.setText(messageBody);
         if (showAsRainbow) {
                if (holder.message.getTag() == null) {
                    objectAnimator = RainbowAnimation.startRainbowAnimation(mContext, messageBody, holder.message);
                    holder.message.setTag(ANIMATED);
                }
            } else {
                objectAnimator.removeAllUpdateListeners();
                objectAnimator.removeAllListeners();
                objectAnimator.end();
                objectAnimator.cancel();
                holder.message.setTag(null);
            }

        LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) holder.chatViewBubble.getLayoutParams();
        LinearLayout.LayoutParams deliveryStatusParams = (LinearLayout.LayoutParams) holder.deliveryStatus.getLayoutParams();
        LinearLayout.LayoutParams gifChatViewLayoutParams = (LinearLayout.LayoutParams) holder.imageViewWrapper.getLayoutParams();

        checkForGif(chatModel, holder);

        if (mCurrentUserId.equals(chatModel.getUserId())) {
            layoutParams.gravity = Gravity.RIGHT;
            layoutParams.rightMargin = Dp.toDps(mContext, 16);
            deliveryStatusParams.gravity = Gravity.RIGHT;
            gifChatViewLayoutParams.gravity = Gravity.RIGHT;

            holder.chatViewBubble.setLayoutParams(layoutParams);
            holder.imageView.setLayoutParams(gifChatViewLayoutParams);

            holder.chatViewBubble.setBackground(ContextCompat.getDrawable(mContext, R.drawable.outgoing_message_bg));
            if (chatModel.getDeliveryStatus().equals(Constants.STATUS_DELIVERED)) {
                if (position >= chatModelList.size() - 1) {
                    holder.deliveryStatus.setVisibility(View.VISIBLE);
                } else {
                    holder.deliveryStatus.setVisibility(View.INVISIBLE);
                }
                holder.deliveryStatus.setText(mContext.getString(R.string.sentText));
            } else if (chatModel.getDeliveryStatus().equals(Constants.STATUS_NOT_DELIVERED)) {
                holder.deliveryStatus.setVisibility(View.VISIBLE);
                if (updating) {
                    holder.deliveryStatus.setText(mContext.getString(R.string.sendingNowText) + percentage + " %");
                } else {
                    holder.deliveryStatus.setText(mContext.getString(R.string.sendingNowText));
                }

            }
        } else {
            holder.chatViewBubble.setBackground(ContextCompat.getDrawable(mContext, R.drawable.incoming_message_bg));
            layoutParams.gravity = Gravity.LEFT;
            gifChatViewLayoutParams.gravity = Gravity.LEFT;

            holder.chatViewBubble.setLayoutParams(layoutParams);
            holder.imageView.setLayoutParams(gifChatViewLayoutParams);
            holder.deliveryStatus.setVisibility(View.INVISIBLE);
        }

    }

这个问题是,如果您注意到Log.d()即使在 objectAnimator 上调用取消和结束后仍然会触发,是的,我已经检查了取消和结束正在被调用。所以我不知道我做错了什么。有人可以帮助我吗?


我看到很多人都在看这篇文章,这意味着他们也遇到了这个问题,所以我以某种方式解决了解决方案...问题是,即使使用静态方法,这个该死的 ObjectAnimator 在循环内完成时,每次都会创建新的引用所以你必须做这样的事情。有一个对象动画师的数组列表,在每次调用时将项目添加到数组列表中。每当你想停止它时,只需简单地循环数组并停止所有对象动画师。这是代码

private ArrayList<ObjectAnimator> objectAnimators = new ArrayList<>();
  public void startRainbowAnimation(Context context,
                                  final String textToShow,
                                  final TextView textViewToAttach) {
    stopCalled = false;
    AnimatedColorSpan span = new AnimatedColorSpan(context);
    final SpannableString spannableString = new SpannableString(textToShow);
    String substring = textToShow;
    int start = textToShow.indexOf(substring);
    int end = start + substring.length();
    spannableString.setSpan(span, start, end, 0);

    ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(
            span, animatedColorSpanFloatProperty, 0, 100);
    objectAnimator.setEvaluator(new FloatEvaluator());

    objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            System.gc();
            if (!stopCalled) {
                textViewToAttach.setText(spannableString);
            }
        }
    });
    objectAnimator.setInterpolator(new LinearInterpolator());
    objectAnimator.setDuration(DateUtils.MINUTE_IN_MILLIS * 3);
    objectAnimator.setRepeatCount(ValueAnimator.INFINITE);
    objectAnimator.start();
    objectAnimators.add(objectAnimator);
}
objectAnimators here is an array list of object animators like this

以下是如何停止所有这些以摆脱无限更新侦听器调用触发的方法。

 public void stopRainbowAnimation() {
    System.gc();
    stopCalled = true;
    if (!objectAnimators.isEmpty()) {
        for (int i = 0; i < objectAnimators.size(); i++) {
            ObjectAnimator eachAnimator = objectAnimators.get(i);
            eachAnimator.setRepeatCount(0);
            eachAnimator.end();
            eachAnimator.cancel();
            eachAnimator.removeAllListeners();
            eachAnimator.removeAllUpdateListeners();
        }
        objectAnimators.clear();
    }
}

希望这会对某人有所帮助

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对象动画师不删除更新监听器android 的相关文章

随机推荐

  • Angular2 Typescript 文件的重复标识符

    在学习 Angular2 TS 快速入门之后 我的项目中的许多文件夹中都出现了重复的文件 对于浏览器 typings browser node modules angular2 typings browser 对于 es6 shim nod
  • 直接将服务注入 AngularJS 指令控制器

    我了解 Angular 依赖注入如何与指令配合使用 但希望澄清一些事情 我有一个虚拟测试指令 如下所示 app directive test function return restrict E scope controller scope
  • 如何在PHP中获取MySQL表结构?加上所有表的列表?

    我需要在 PHP 中运行什么查询才能获取数据库中给定表的结构 我需要运行什么查询才能获取所有表的列表 要获取表的列列表 请使用 DESCRIBE SQL 语句 语法如下 DESCRIBE TableName 要获取数据库上的表列表 请使用以
  • 如何使用 Delphi XE2 IDE 搜索来搜索

    我一直使用搜索来在 庞大的 应用程序源中查找内容 因此搜索有效性对我来说非常重要 目前在 Delphi XE2 IDE 中我喜欢使用 在文件中查找 包括子目录 没有其他花哨的东西 只是一个文本关键字 这工作正常 但我真正想做的是扩展我现在正
  • AFNetworking 3 x-www-form-urlencoded 发布数据

    I m trying to post data with x www form urlencoded body Posting via postman it is ok 但我无法通过 afnetworking 3 做到这一点 这是我的代码
  • 如何将 QtCreator 项目转换为 Visual Studio 项目

    我有一个 QtCreator 项目文件 pro 如何将其转换为Visual Studio 2008项目 sln 您还可以使用 qmake 命令来执行此操作 转到项目目录并输入 qmake tp vc
  • 如何使sequelize.sync()省略一些模型?

    我在数据库 mysql 中使用表和视图 因此对于开发 测试环境我想使用sync 但它在视图上崩溃 我可以以某种方式省略这些模型吗 当我想通过 Sequelize 创建和使用视图时 我使用与 Crusader 的答案非常相似的方法 在这种情况
  • 在 OAuth2.0 中使用 Facebook 访问令牌作为资源所有者凭据

    OAuth 2 0 规范定义了资源所有者密码凭证授予类型 https datatracker ietf org doc html draft ietf oauth v2 26 section 4 3 它允许直接使用资源所有者密码凭据 即用户
  • JSch get() 失败并出现 NullPointerException

    我有一个 Jax RS 服务器 它应该保存可通过 ssh 访问的文件列表 然后我可以通过 HTTP 下载或流式传输 我一直在尝试使用 JSch 的 SFTP 通道读取文件 但我不断收到NullPointerException 这是Messa
  • 如何在 C++ 中前向声明 std::set?

    为了加快编译过程 我正在尝试简化我的头文件MyClass hpp通过前向声明 STL 容器 例如 std vector std set But std set can NOT在以下代码中进行前向声明 同时std vector can be
  • 在地图函数中迭代应用 ggplot 函数

    我想为数据集中的所有变量生成一系列直方图 但显然我没有正确准备数据以便在地图函数中使用 library tidyverse mtcars gt select wt disp hp gt map function x ggplot aes x
  • 仅在特定服务器上调用delayed_job capistrano任务

    我有一个专门的服务器用于delayed job 任务 我想启动 停止和重新启动delayed job工作人员only这个服务器 我正在使用delayed job提供的capistrano食谱 当我只有 1 台服务器时 这是我的配置 befo
  • 仍然无法针对带有 Salat / Casbah 的 Play FakeApp 运行多个测试

    我以为我已经修好了问题 https stackoverflow com questions 12028218 running multiple tests within the same fakeapplication in play 2
  • 为什么 receive_boot_completed 在我的设备上不起作用?

    我正在开发一些需要使用的应用程序receive boot completed重新启动以重置一些警报 它可以在模拟器和 Samsung tab 2 10 1 上正常工作 但它不能在我的 android 版本 2 2 1 的 Galaxy Mi
  • jQuery/javascript 用户单击和以编程方式单击复选框的不同行为

    有点难以解释 所以我设置了一个 jsFiddlehere http jsfiddle net BCECy 基本上 当用户单击复选框时 我会触发一些行为 在另一个地方 我尝试以编程方式单击复选框 我需要看到完全相同的行为 它不起作用 似乎与单
  • Vim 中每行末尾的美元符号(“$”)是什么

    我对 Vim 还比较陌生 每当我启动 Vim 时使用vim LearnRuby rb 每行都会出现一个美元符号 Why set nolist 将关闭当前缓冲区的特殊字符 例如制表符显示为 I和行尾字符显示为 然而 如果它在你跑步时始终如一地
  • .hgignore 语法仅忽略文件,而不忽略目录?

    我有一个我似乎无法理解的问题 我在 Windows 上使用 TortoiseHg 版本 0 7 5 但在 Linux 上我遇到了同样的问题 这里是 My hgignore file syntax regexp 我想要实现的是将 hg 存储库
  • PHP - UPLOAD_ERR_NO_TMP_DIR

    我正在使用 Cbeyond www cbeyond com 你们中的一些人可能熟悉它们 作为启用 PHP 的虚拟主机 当我检查如下时 我的 PHP 上传功能遇到问题 error FILES uploadedfile error echo e
  • Graphql 字段在类型上不存在

    浏览完 Graphql 的文档后 我开始在一个玩具 Rails reactJS 项目上实现它 这些项目允许用户通过设备登录 然后访问显示艺术家列表的虚拟 艺术家路径 一切似乎都工作正常 直到我尝试使用 React 应用程序中的 GraphQ
  • 对象动画师不删除更新监听器android

    美好的一天 我有一个场景 这个半正常的对象动画师不断地反复触发 导致堆增长 当然在某些时候还会出现内存不足问题 这是如何进行的 我为这样的彩虹动画制作了静态方法 public static ObjectAnimator startRainb