MyLove.getInstance() == null;

在编程世界中,作者遇到了一个棘手的问题——当使用MyLove.getInstance()时,程序抛出了NullPointException。这导致作者陷入混乱,尝试多次运行程序却未能解决问题。作者反思是否犯了低级错误,但意识到这可能是由于MyLove类内部的内核问题。作者表达了对于深入调试的抗拒,因为相信这是由深层次的内核问题导致,而非简单的异常处理疏漏。最终,作者决定接受现实,在MyLove为空的情况下继续进行开发。

当MyLove.getInstance() 抛出了NullPointException的时候.

我丢掉了我的理智,再运行一次,

我希望这只是偶然,

然而我应该失望,因为我依然看到Null;

也许你会说我犯了一个低级的错误,没有捕获这个异常.


              但是在属于你的世界,我从来没有做过异常处理

因为我从不相信,你会从中抽离,让我的MyLove抛空.

              所有归属你的方法都不再为我调用.我的心乱了.烦了,燥了.

我不想去debug.因为我知道,我一定查不到原因.

因为,如果你为空.那是内核出了问题.我往底下查有什么意义,

我根本不愿意去修改你唯一存在的内核.

从此以后,我只能在MyLove空着地环境下做一切.

package com.example.lovedemo.activity; import androidx.appcompat.app.AppCompatActivity; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.app.AlertDialog; import android.content.Intent; import android.graphics.drawable.AnimationDrawable; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.KeyEvent; import android.view.ViewGroup; import android.widget.FrameLayout; import android.widget.ImageView; import com.example.lovedemo.R; import com.example.lovedemo.dialog.CloseAlertDialogUtils; import com.example.lovedemo.dialog.QuitDialog; import com.example.lovedemo.dialog.VindicateDialog; import com.example.lovedemo.tools.Utils; import com.example.lovedemo.view.StarRainView; import java.util.Random; public class MainActivity extends AppCompatActivity { private FrameLayout container; // 多种星形资源 private int[] starResIds = { R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a5, R.drawable.a6, R.drawable.a7, R.drawable.a8, R.drawable.a9, R.drawable.a10, R.drawable.a11, R.drawable.a12, R.drawable.a13, R.drawable.a14, R.drawable.a15, R.drawable.a16, R.drawable.a17, R.drawable.a18, R.drawable.a19 }; private int[] starResId = { R.drawable.xin1, R.drawable.xin2, R.drawable.xin3, R.drawable.xin4, R.drawable.xxing }; private Random random = new Random(); private long currentDelay = 0; private final long delayBetweenStars = 500; // 每颗星星间隔时间 private Handler starHandler = new Handler(Looper.getMainLooper()); private Runnable starRunnable; private boolean isStarAnimationRunning = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); container = findViewById(R.id.container); // 依次绘制图形 drawLetterI(); drawHeart(); drawLetterU(); startRandomStarAnimation(); } // 创建带有动画的 ImageView private ImageView createStar(float x, float y) { ImageView imageView = new ImageView(this); imageView.setImageResource(starResIds[random.nextInt(starResIds.length)]); imageView.setLayoutParams(new FrameLayout.LayoutParams(35, 35)); imageView.setX(x); imageView.setY(y); imageView.setAlpha(0f); imageView.setScaleX(0.5f); imageView.setScaleY(0.5f); // 缩放和透明度动画 ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f); ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(imageView, "scaleX", 0.5f, 1f); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(imageView, "scaleY", 0.5f, 1f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(alphaAnim, scaleXAnim, scaleYAnim); animatorSet.setDuration(3500); // 延迟执行 new Handler(Looper.getMainLooper()).postDelayed(animatorSet::start, currentDelay); currentDelay += delayBetweenStars; return imageView; } // 绘制字母 I private void drawLetterI() { int centerX = 530; int startY = 200; // 绘制顶部横杠 for (int i = -2; i < 3; i++) { ImageView topBarStar = createStar(centerX + i * 40, startY - 40); container.addView(topBarStar); } // 绘制垂直列(中间部分) for (int i = 0; i < 9; i++) { float y = startY + i * 40; ImageView star = createStar(centerX, y); container.addView(star); } // 绘制底部横杠 for (int i = -2; i < 3; i++) { ImageView bottomBarStar = createStar(centerX + i * 40, startY + 8 * 40); container.addView(bottomBarStar); } } // 绘制心形图案 private void drawHeart() { int centerX = 530; int centerY = 900; int size = 15; // 设置图片资源,例如你有一个叫 "heart_image" 的图片资源 for (double t = 0; t < 2 * Math.PI; t += 0.2) { double xVal = 16 * Math.pow(Math.sin(t), 3); double yVal = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t); float px = (float) (centerX + xVal * size); float py = (float) (centerY - yVal * size); ImageView star = createStar(px, py); container.addView(star); } // 添加心形中央图片并设置缩放动画 new Handler(Looper.getMainLooper()).postDelayed(() -> { ImageView heartImage = new ImageView(this); heartImage.setImageResource(R.drawable.h_m_m); // 使用自己的心形图片资源 heartImage.setLayoutParams(new FrameLayout.LayoutParams(260, 260)); // 设置合适的大小 heartImage.setX(centerX - 105); // 设置图片X位置 heartImage.setY(centerY - 65); // 设置图片Y位置 // 设置缩放动画 ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(heartImage, "scaleX", 0f, 1f); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(heartImage, "scaleY", 0f, 1f); ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(heartImage, "alpha", 0f, 1f); AnimatorSet heartAnimatorSet = new AnimatorSet(); heartAnimatorSet.playTogether(scaleXAnim, scaleYAnim, alphaAnim); heartAnimatorSet.setDuration(3500); // 设置动画时长 container.addView(heartImage); heartAnimatorSet.start(); }, 20 * 1000); // 设置延迟,在绘制完心形图案后开始执行 } // 绘制字母 U(底部为圆弧) private void drawLetterU() { long totalDuration = 0; int startX = 410; int startY = 1300; // 左侧横线 for (int i = -6; i < 8; i++) { float x = (float) (startX + i * -5); ImageView star = createStar(x, startY); container.addView(star); } // 右侧横线 for (int i = -6; i < 8; i++) { float x = startX + i * -5; ImageView star = createStar(x + 250, startY); container.addView(star); } // 左侧竖线 for (int i = 0; i < 8; i++) { float y = startY + i * 40; ImageView star = createStar(startX, y); container.addView(star); } // 右侧竖线(更宽了) for (int i = 0; i < 8; i++) { float y = startY + i * 40; ImageView star = createStar(startX + 250, y); container.addView(star); } // 底部绘制一个圆弧形(近似) int centerX = startX + 125; // 新增宽度后的新中点 int centerY = startY + 7 * 40; // Y 不变 int radius = 110; // 增大半径以适应新宽度 int points = 9; // 更多点数,圆弧更平滑 for (int i = 0; i < points; i++) { double angle = Math.PI * i / (points - 1); // 从 π 到 2π 的角度(下半圆) float x = (float) (centerX + radius * Math.cos(angle)); float y = (float) (centerY + radius * Math.sin(angle)); ImageView star = createStar(x, y); container.addView(star); totalDuration += 5500; } new Handler(Looper.getMainLooper()).postDelayed(this::triggerCornerAnimations, totalDuration); } private void triggerCornerAnimations() { // 右上:从左向右移动 showCornerImageWithTranslation(R.drawable.up_right, container.getWidth(), 0, container.getWidth() - 150, -35); // 中间:从左到中间移动 showCornerImageWithTranslation(R.drawable.upmidd, -150, 100, container.getWidth() / 2 - 130, -35, 250, 150); // 左上:从左移动到左上 showCornerImageWithTranslation(R.drawable.up_left, -100, 0, 0, -35); // 左下角动画:保持缩放效果 animateCorner(R.drawable.down_left, -10, container.getHeight() - 150); //下边距动画:保持缩放效果 Utils.animateCorner(R.drawable.downmidd, container.getWidth() / 2 - 120, container.getHeight() - 125, MainActivity.this, container, 250, 200); // 右下角动画:保持缩放效果 animateCorner(R.drawable.down_right, container.getWidth() - 140, container.getHeight() - 150); // 延迟执行,在所有动画完成后添加心形图案下方的图片 new Handler(Looper.getMainLooper()).postDelayed(this::addImagesNearHeart, 6500); // 调整延迟时间确保所有动画完成 } private void animateCorner(int resId, float startX, float startY) { ImageView cornerImage = new ImageView(this); cornerImage.setImageResource(resId); cornerImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150)); cornerImage.setX(startX); cornerImage.setY(startY); cornerImage.setAlpha(0f); AnimatorSet animatorSet = new AnimatorSet(); // 缩放动画:保持原有逻辑 cornerImage.setScaleX(0.5f); cornerImage.setScaleY(0.5f); ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(cornerImage, "scaleX", 0.5f, 1f); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(cornerImage, "scaleY", 0.5f, 1f); ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(cornerImage, "alpha", 0f, 1f); animatorSet.playTogether(scaleXAnim, scaleYAnim, alphaAnim); animatorSet.setDuration(3500); container.addView(cornerImage); animatorSet.start(); } private void showCornerImageWithTranslation(int resId, float startX, float startY, float endX, float endY) { ImageView cornerImage = new ImageView(this); cornerImage.setImageResource(resId); cornerImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150)); cornerImage.setX(startX); cornerImage.setY(startY); cornerImage.setAlpha(0f); cornerImage.setScaleX(1f); cornerImage.setScaleY(1f); container.addView(cornerImage); // Alpha animation ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(cornerImage, "alpha", 0f, 1f); // Translation animations ObjectAnimator translateXAnim = ObjectAnimator.ofFloat(cornerImage, "x", startX, endX); ObjectAnimator translateYAnim = ObjectAnimator.ofFloat(cornerImage, "y", startY, endY); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(alphaAnim, translateXAnim, translateYAnim); animatorSet.setDuration(3500); animatorSet.start(); } // 创建平移动画的辅助方法 private void showCornerImageWithTranslation(int resId, float startX, float startY, float endX, float endY, int width, int height) { ImageView cornerImage = new ImageView(this); cornerImage.setImageResource(resId); // 设置图片的宽度和高度 cornerImage.setLayoutParams(new FrameLayout.LayoutParams(width, height)); cornerImage.setX(startX); cornerImage.setY(startY); cornerImage.setAlpha(0f); cornerImage.setScaleX(1f); cornerImage.setScaleY(1f); container.addView(cornerImage); // Alpha 动画 ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(cornerImage, "alpha", 0f, 1f); ObjectAnimator translateXAnim = ObjectAnimator.ofFloat(cornerImage, "x", startX, endX); ObjectAnimator translateYAnim = ObjectAnimator.ofFloat(cornerImage, "y", startY, endY); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(alphaAnim, translateXAnim, translateYAnim); animatorSet.setDuration(3500); // 在动画结束后,添加缩放动画的新图片 animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); // 在图片的正中心创建新图片 float centerX = (float) (cornerImage.getX() + (cornerImage.getWidth() / 1.6)); float centerY = (float) (cornerImage.getY() + (cornerImage.getHeight() / 1.9)); // 创建新图片 ImageView zoomImage = new ImageView(MainActivity.this); zoomImage.setImageResource(R.drawable.love_middle_down); // 替换成你的新图片资源 zoomImage.setLayoutParams(new FrameLayout.LayoutParams(50, 50)); // 设置缩放图片的大小 container.addView(zoomImage); // 设置新图片的初始位置为正中心 zoomImage.setX(centerX - 50); // 100/2 使得图片位于中心 zoomImage.setY(centerY - 50); // 100/2 使得图片位于中心 // 创建缩放动画 ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(zoomImage, "scaleX", 0f, 1f); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(zoomImage, "scaleY", 0f, 1f); AnimatorSet scaleAnimatorSet = new AnimatorSet(); scaleAnimatorSet.playTogether(scaleXAnim, scaleYAnim); scaleAnimatorSet.setDuration(3500); // 设定缩放动画的时长 scaleAnimatorSet.start(); // 在屏幕的左右两边添加缩放动画的新图片 // 左侧图片 ImageView leftImage = new ImageView(MainActivity.this); leftImage.setImageResource(R.drawable.midd_midd_left); // 替换成你左侧的图片资源 leftImage.setLayoutParams(new FrameLayout.LayoutParams(150, ViewGroup.LayoutParams.MATCH_PARENT)); // 设置左侧图片的大小 container.addView(leftImage); // 设置左侧图片的位置 leftImage.setX(0); // 屏幕左边 leftImage.setY(centerY - 50); // 垂直居中 // 创建左侧图片的缩放动画 ObjectAnimator leftScaleXAnim = ObjectAnimator.ofFloat(leftImage, "scaleX", 0f, 1f); ObjectAnimator leftScaleYAnim = ObjectAnimator.ofFloat(leftImage, "scaleY", 0f, 1f); AnimatorSet leftScaleAnimatorSet = new AnimatorSet(); leftScaleAnimatorSet.playTogether(leftScaleXAnim, leftScaleYAnim); leftScaleAnimatorSet.setDuration(3500); leftScaleAnimatorSet.start(); // 右侧图片 ImageView rightImage = new ImageView(MainActivity.this); rightImage.setImageResource(R.drawable.midd_midd_right); // 替换成你右侧的图片资源 rightImage.setLayoutParams(new FrameLayout.LayoutParams(150, ViewGroup.LayoutParams.MATCH_PARENT)); // 设置右侧图片的大小 container.addView(rightImage); // 设置右侧图片的位置 rightImage.setX(getResources().getDisplayMetrics().widthPixels - 150); // 屏幕右边 rightImage.setY(centerY - 50); // 垂直居中 // 创建右侧图片的缩放动画 ObjectAnimator rightScaleXAnim = ObjectAnimator.ofFloat(rightImage, "scaleX", 0f, 1f); ObjectAnimator rightScaleYAnim = ObjectAnimator.ofFloat(rightImage, "scaleY", 0f, 1f); AnimatorSet rightScaleAnimatorSet = new AnimatorSet(); rightScaleAnimatorSet.playTogether(rightScaleXAnim, rightScaleYAnim); rightScaleAnimatorSet.setDuration(3500); rightScaleAnimatorSet.start(); } }); animatorSet.start(); } private void addImagesNearHeart() { // 获取心形图案的位置 int centerX = 530; int centerY = 900; // 左侧图片 ImageView leftImage = new ImageView(this); leftImage.setImageResource(R.drawable.love_m_left); // 替换成你的左侧图片资源 leftImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150)); // 设置图片大小 leftImage.setX(centerX - 250); // 设置位置,心形图片左侧 leftImage.setY(centerY + 100); // 设置位置,心形图片下方 leftImage.setAlpha(0f); // 初始透明度为0 container.addView(leftImage); // 右侧图片 ImageView rightImage = new ImageView(this); rightImage.setImageResource(R.drawable.hudei); // 替换成你的右侧图片资源 rightImage.setLayoutParams(new FrameLayout.LayoutParams(150, 150)); // 设置图片大小 rightImage.setX(centerX + 280); // 设置位置,心形图片右侧 rightImage.setY(centerY + 50); // 设置位置,心形图片下方 rightImage.setAlpha(0f); // 初始透明度为0 container.addView(rightImage); // 缩放动画 ObjectAnimator scaleXLeft = ObjectAnimator.ofFloat(leftImage, "scaleX", 0f, 1f); ObjectAnimator scaleYLeft = ObjectAnimator.ofFloat(leftImage, "scaleY", 0f, 1f); ObjectAnimator alphaLeft = ObjectAnimator.ofFloat(leftImage, "alpha", 0f, 1f); ObjectAnimator scaleXRight = ObjectAnimator.ofFloat(rightImage, "scaleX", 0f, 1f); ObjectAnimator scaleYRight = ObjectAnimator.ofFloat(rightImage, "scaleY", 0f, 1f); ObjectAnimator alphaRight = ObjectAnimator.ofFloat(rightImage, "alpha", 0f, 1f); // 创建 AnimatorSet AnimatorSet animatorSetLeft = new AnimatorSet(); animatorSetLeft.playTogether(scaleXLeft, scaleYLeft, alphaLeft); animatorSetLeft.setDuration(3500); // 设置动画时长 AnimatorSet animatorSetRight = new AnimatorSet(); animatorSetRight.playTogether(scaleXRight, scaleYRight, alphaRight); animatorSetRight.setDuration(3500); // 设置动画时长 animatorSetRight.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { @Override public void run() { int type = 2; VindicateDialog dialog = VindicateDialog.getInstance(); VindicateDialog.showConfirmDialog(MainActivity.this, "", "还没结束哦,请点击同意进入下一个页面哦= ̄ω ̄=",type); dialog.setMonDialogButtonClickListener(new VindicateDialog.OnDialogButtonClickListener() { @Override public void onPositiveButtonClick(AlertDialog dialog) { Intent intent = new Intent(MainActivity.this, VindicateActivity.class); startActivity(intent); finish(); //关闭当前Activity } @Override public void onNegativeButtonClick(AlertDialog dialog) { //点击不同意按钮关闭应用 dialog.dismiss(); CloseAlertDialogUtils instance = CloseAlertDialogUtils.getInstance(); CloseAlertDialogUtils.showConfirmDialog(MainActivity.this, "", "小姐姐确定要这么狠心的离开吗?还有惊喜哦,拜托看完好吗~(>﹏<)"); instance.setMonDialogButtonClickListener(new CloseAlertDialogUtils.OnDialogButtonClickListener() { @Override public void onClosePositiveButtonClick(AlertDialog dialog) { Intent intent = new Intent(MainActivity.this, VindicateActivity.class); startActivity(intent); finish(); //关闭当前Activity } @Override public void onCloseNegativeButtonClick(AlertDialog dialog) { int type = 2; //点击不同意按钮关闭应用 dialog.dismiss(); QuitDialog instance = QuitDialog.getInstance(); QuitDialog.showConfirmDialog(MainActivity.this, "", "即使不知归期,我也会默默等待,挥手道别,是为了更好的相遇。这次是真的要再见了小姐姐o(*≧▽≦)ツ",type); instance.setMonDialogButtonClickListener(new QuitDialog.OnDialogButtonClickListener() { @Override public void onClosePositiveButtonClick(AlertDialog dialog) { } @Override public void onCloseNegativeButtonClick(AlertDialog dialog) { dialog.dismiss(); System.exit(0); } }); } }); } }); } }, 10000); // 动画结束后延迟10秒 } }); // 启动动画 animatorSetLeft.start(); animatorSetRight.start(); } private void startRandomStarAnimation() { isStarAnimationRunning = true; starRunnable = new Runnable() { @Override public void run() { if (!isStarAnimationRunning) return; // 随机选择资源 int resId = starResId[random.nextInt(starResId.length)]; // 随机位置 int screenWidth = getResources().getDisplayMetrics().widthPixels; int screenHeight = getResources().getDisplayMetrics().heightPixels; float x = random.nextInt(screenWidth - 100); // 留出边距 float y = random.nextInt(screenHeight - 100); ImageView star = new ImageView(MainActivity.this); star.setImageResource(resId); star.setLayoutParams(new FrameLayout.LayoutParams(100, 100)); star.setX(x); star.setY(y); star.setAlpha(0f); star.setScaleX(0.5f); star.setScaleY(0.5f); // 添加到容器中 container.addView(star); // 动画 ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(star, "alpha", 0f, 1f, 0f); ObjectAnimator scaleUpX = ObjectAnimator.ofFloat(star, "scaleX", 0.5f, 1.2f); ObjectAnimator scaleUpY = ObjectAnimator.ofFloat(star, "scaleY", 0.5f, 1.2f); ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(star, "scaleX", 1.2f, 0.5f); ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(star, "scaleY", 1.2f, 0.5f); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playSequentially( ObjectAnimator.ofFloat(star, "alpha", 0f, 1f), scaleUpX, scaleUpY, scaleDownX, scaleDownY, ObjectAnimator.ofFloat(star, "alpha", 1f, 0f) ); animatorSet.setDuration(3500); // 动画结束后移除视图 animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { container.removeView(star); } }); animatorSet.start(); // 下一次随机延迟执行 long nextDelay = random.nextInt(1000) + 500; // 0.5s ~ 1.5s starHandler.postDelayed(this, nextDelay); } }; starHandler.post(starRunnable); } //监听退出 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { Utils.exit(MainActivity.this); return false; } return super.onKeyDown(keyCode, event); } //停止星星动画 private void stopRandomStarAnimation() { isStarAnimationRunning = false; starHandler.removeCallbacks(starRunnable); } @Override protected void onDestroy() { stopRandomStarAnimation(); super.onDestroy(); } } package com.example.lovedemo.activity; import androidx.appcompat.app.AppCompatActivity; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.TypedValue; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.example.lovedemo.R; import com.example.lovedemo.view.StarConcentricKnotView; import java.util.concurrent.atomic.AtomicInteger; public class VindicateActivity extends AppCompatActivity { private FrameLayout container; private int[] heartResId = { R.drawable.right1, R.drawable.right2 }; private int[] heartResIds = { R.drawable.up0, R.drawable.up1 }; private int currentHeartIndex = 0; // 当前心形索引 private long delayBetweenHearts = 100; // 每个心形之间的延迟时间 private long currentDelay = 0; private long baseDelay = 0; // 全局基础延迟时间 private final long animationGroupInterval = 3500; // 每组动画之间间隔 1.5 秒 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_vindicate); container = findViewById(R.id.container); // ✨ 添加 ConcentricKnotView 到容器中 StarConcentricKnotView knotView = new StarConcentricKnotView(this); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ); container.addView(knotView, params); // ✨ 使用 ViewTreeObserver 确保 View 已完成布局后再启动动画 knotView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { knotView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); drawTopBorder(); // 主边框 drawTopBorderDots(); // 点缀边框 drawLeftBorder(); drawRightBorder(); drawBottomBorder(); drawBottomBorderDots(); // 点缀边框 - 下 } // 创建带动画的心形 ImageView private ImageView createHeart(float x, float y, boolean isSmall, long initialDelay) { ImageView heart = new ImageView(this); if (isSmall) { heart.setImageResource(heartResId[currentHeartIndex]); currentHeartIndex = (currentHeartIndex + 1) % heartResId.length; heart.setLayoutParams(new FrameLayout.LayoutParams(50, 50)); heart.setAlpha(0f); heart.setScaleX(0.5f); heart.setScaleY(0.5f); } else { heart.setImageResource(heartResIds[currentHeartIndex]); currentHeartIndex = (currentHeartIndex + 1) % heartResIds.length; heart.setLayoutParams(new FrameLayout.LayoutParams(60, 60)); heart.setAlpha(0.5f); heart.setScaleX(0.3f); heart.setScaleY(0.3f); } heart.setX(x); heart.setY(y); ObjectAnimator alpha = ObjectAnimator.ofFloat(heart, "alpha", 0f, 1f); ObjectAnimator scaleX = ObjectAnimator.ofFloat(heart, "scaleX", 0f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(heart, "scaleY", 0f, 1f); AnimatorSet set = new AnimatorSet(); set.playTogether(alpha, scaleX, scaleY); set.setDuration(isSmall ? 2500 : 2800); new Handler(Looper.getMainLooper()).postDelayed(set::start, initialDelay + currentDelay); currentDelay += delayBetweenHearts; return heart; } // 绘制上边框 private void drawTopBorder() { int screenHeight = getResources().getDisplayMetrics().heightPixels; int screenWidth = getResources().getDisplayMetrics().widthPixels; int spacing = 40; // 心形间距 int offset = (int) convertDpToPx(15); // 错落偏移量 for (int i = 0; i < screenWidth / spacing + 1; i++) { float waveOffset = (float) Math.sin(i * Math.PI / 4) * offset; float x = i * spacing; float y = 0; // 奇数索引项加上偏移 if (i % 2 == 1) { y += waveOffset; } container.addView(createHeart(x, y,true,baseDelay)); } baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay } private void drawTopBorderDots() { int screenWidth = getResources().getDisplayMetrics().widthPixels; int spacing = 60; // 更稀疏一些 int offset = (int) convertDpToPx(10); // 小波浪偏移量 int baseY = 20; // 轻微偏移,让点缀图和主图有层次感 for (int i = 0; i < screenWidth / spacing + 1; i++) { float waveOffset = (float) Math.sin(i * Math.PI / 4) * offset; float x = i * spacing; float y = baseY + waveOffset; container.addView(createHeart(x, y,false,baseDelay)); } baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay } // 绘制左边框 private void drawLeftBorder() { int screenHeight = getResources().getDisplayMetrics().heightPixels; int spacing = 40; AnimatorSet leftBorderAnimatorSet = new AnimatorSet(); for (int i = 0; i < screenHeight / spacing + 1; i++) { float x = 0; float y = i * spacing; container.addView(createHeart(x, y,true,baseDelay)); } baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay } // 绘制右边框 private void drawRightBorder() { int screenHeight = getResources().getDisplayMetrics().heightPixels; int screenWidth = getResources().getDisplayMetrics().widthPixels; int spacing = 40; AnimatorSet rightBorderAnimatorSet = new AnimatorSet(); for (int i = 0; i < screenHeight / spacing + 1; i++) { float x = screenWidth - convertDpToPx(15); float y = i * spacing; container.addView(createHeart(x, y,true,baseDelay)); } baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay } // 绘制下边框 private void drawBottomBorder() { int screenHeight = getResources().getDisplayMetrics().heightPixels; int screenWidth = getResources().getDisplayMetrics().widthPixels; int spacing = 40; int offset = (int) convertDpToPx(15); int baseY = (int) (screenHeight - convertDpToPx(40)); for (int i = 0; i < screenWidth / spacing + 1; i++) { float waveOffset = (float) Math.sin(i * Math.PI / 4) * offset; float x = i * spacing; float y = baseY; if (i % 2 == 1) { y -= waveOffset; } container.addView( createHeart(x, y, true, baseDelay)); } baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay } private void drawBottomBorderDots() { int screenWidth = getResources().getDisplayMetrics().widthPixels; int spacing = 30; int offset = (int) convertDpToPx(12); int baseY = (int) (getResources().getDisplayMetrics().heightPixels - convertDpToPx(40)) - 20; float phaseShift = 2.0f; // 相位偏移 for (int i = 0; i < screenWidth / spacing + 2; i++) { float waveOffset = (float) Math.sin((i + phaseShift) * Math.PI / 4) * offset; float x = i * spacing; float y = baseY - waveOffset; container.addView(createHeart(x, y,false,baseDelay)); } baseDelay += animationGroupInterval; // 这里只在整组结束后加一次 delay // 在最后加上对 addAnimatedTextView 的延迟调用 new Handler(Looper.getMainLooper()).postDelayed(this::addAnimatedTextView, baseDelay + animationGroupInterval); // 再等一组动画时间确保完全结束 } //添加文本动画 private void addAnimatedTextView() { String fullText = getResources().getString(R.string.second_words); String[] lines = fullText.split("\n"); LinearLayout verticalContainer = new LinearLayout(this); verticalContainer.setOrientation(LinearLayout.VERTICAL); FrameLayout.LayoutParams containerParams = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT ); containerParams.leftMargin = (int) convertDpToPx(16); containerParams.topMargin = (int) convertDpToPx(25); verticalContainer.setLayoutParams(containerParams); container.addView(verticalContainer); int charDelay = 300; AtomicInteger globalIndex = new AtomicInteger(); int totalCharCount = 0; for (String line : lines) { LinearLayout textContainer = new LinearLayout(this); textContainer.setOrientation(LinearLayout.HORIZONTAL); verticalContainer.addView(textContainer); char[] chars = line.toCharArray(); for (int i = 0; i < chars.length; i++) { final int index = globalIndex.getAndIncrement(); final char c = chars[i]; TextView charTextView = new TextView(this); charTextView.setText(String.valueOf(c)); charTextView.setTextSize(12); charTextView.setTextColor(Color.parseColor("#FF69B4")); charTextView.setAlpha(0f); charTextView.setScaleX(0.5f); charTextView.setScaleY(0.5f); textContainer.addView(charTextView); ValueAnimator animator = ValueAnimator.ofFloat(0, 1); animator.setDuration(1000); animator.setStartDelay(charDelay * index); animator.addUpdateListener(animation -> { float value = (float) animation.getAnimatedValue(); charTextView.setAlpha(value); charTextView.setScaleX(0.5f + 0.5f * value); charTextView.setScaleY(0.5f + 0.5f * value); }); animator.start(); totalCharCount++; } } // 计算总延迟时间 = 最后一个字符的 startDelay + 动画持续时间 + 10ms long totalDuration = charDelay * (totalCharCount - 1) + 1000 + 10000; // 使用 Handler 延迟跳转 new Handler(Looper.getMainLooper()).postDelayed(() -> { // 在这里执行跳转逻辑 startActivity(new Intent(VindicateActivity.this, VowsActivity.class)); finish(); }, totalDuration); } // 将 dp 转换为 px private float convertDpToPx(float dp) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics()); } @Override protected void onDestroy() { container.removeAllViews(); super.onDestroy(); } } package com.example.lovedemo.activity; import androidx.appcompat.app.AppCompatActivity; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.os.Bundle; import android.os.Handler; import android.util.DisplayMetrics; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import com.example.lovedemo.R; import com.example.lovedemo.view.CustomCombinedTextView; import java.util.ArrayList; import java.util.List; import java.util.Random; public class VowsActivity extends AppCompatActivity { private FrameLayout container; private int[] starResIds = { R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a5, R.drawable.a6, R.drawable.a7, R.drawable.a8, R.drawable.a9, R.drawable.a10, R.drawable.a11, R.drawable.a12, R.drawable.a13, R.drawable.a14, R.drawable.a15, R.drawable.a16, R.drawable.a17, R.drawable.a18, R.drawable.a19 }; private Random random = new Random(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_oath); container = findViewById(R.id.container); // 确保 container 已经正确绑定到布局文件中的 FrameLayout if (container == null) { throw new IllegalStateException("Container not found in layout"); } addRotatingZoomingImageView(); // 创建 CustomCombinedTextView 并设置参数 CustomCombinedTextView textView = new CustomCombinedTextView(this); FrameLayout.LayoutParams params = new FrameLayout.LayoutParams( FrameLayout.LayoutParams.WRAP_CONTENT, FrameLayout.LayoutParams.WRAP_CONTENT ); params.topMargin = 50; // 可以根据需要调整位置 params.leftMargin = 0; // 可以根据需要调整位置 textView.setLayoutParams(params); // 添加到 container 布局中 container.addView(textView); // 启动组合动画 textView.startCombinedAnimation(100); // 每个字间隔 300ms } private void addRotatingZoomingImageView() { // 创建 ImageView ImageView imageView = new ImageView(this); imageView.setImageResource(R.drawable.bee); // 设置宽高为 200px,并设置缩放类型 imageView.setLayoutParams(new FrameLayout.LayoutParams(200, 200)); imageView.setScaleType(ImageView.ScaleType.CENTER_INSIDE); // 防止裁剪 // 初始透明度和缩放 imageView.setAlpha(0f); imageView.setScaleX(0.5f); imageView.setScaleY(0.5f); // 初始位置设为屏幕外(左上角外侧) float startX = 0; float startY = 0; imageView.setX(startX); imageView.setY(startY); // 添加到容器 container.addView(imageView); // 启动动画 startTranslateAndZoomAnimation(imageView); } private void startTranslateAndZoomAnimation(ImageView imageView) { float endX = 100; // 最终位置 x float endY = 50; // 最终位置 y // 缩放动画 ObjectAnimator scaleXAnim = ObjectAnimator.ofFloat(imageView, "scaleX", 0.5f, 1f); ObjectAnimator scaleYAnim = ObjectAnimator.ofFloat(imageView, "scaleY", 0.5f, 1f); // 平移动画 ObjectAnimator translateXAnim = ObjectAnimator.ofFloat(imageView, "x", -200, endX); ObjectAnimator translateYAnim = ObjectAnimator.ofFloat(imageView, "y", 0, endY); // 透明度动画 ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(imageView, "alpha", 0f, 1f); // 组合动画 AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(scaleXAnim, scaleYAnim, translateXAnim, translateYAnim, alphaAnim); animatorSet.setDuration(2500); animatorSet.setInterpolator(new AccelerateDecelerateInterpolator()); // 动画监听器 animatorSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { System.out.println("平移+缩放动画已完成"); startFallingStarAnimation(endX + 150, endY); // 在原图右侧开始掉星星 } }); // 启动动画 animatorSet.start(); } private void startFallingStarAnimation(float startX, float startY) { final int STAR_COUNT = 90; final List<ImageView> stars = new ArrayList<>(); final Handler handler = new Handler(); DisplayMetrics displayMetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); int screenHeight = displayMetrics.heightPixels; float finalY = screenHeight - 100; for (int i = 0; i < STAR_COUNT; i++) { final int index = i; handler.postDelayed(() -> { ImageView starView = new ImageView(this); starView.setImageResource(starResIds[random.nextInt(starResIds.length)]); starView.setLayoutParams(new FrameLayout.LayoutParams(50, 50)); starView.setX(startX + index * 40); // x轴偏移避免重叠 starView.setY(startY); starView.setPivotX(50); // 100x100 图片的一半 starView.setPivotY(50); container.addView(starView); stars.add(starView); // 下落动画 ObjectAnimator fallAnim = ObjectAnimator.ofFloat(starView, "y", startY, finalY); fallAnim.setDuration(1000); fallAnim.setInterpolator(new AccelerateInterpolator()); // 第一次弹跳 ObjectAnimator bounceAnim1 = ObjectAnimator.ofFloat(starView, "y", finalY, finalY - 100); bounceAnim1.setDuration(500); bounceAnim1.setInterpolator(new DecelerateInterpolator()); // 第二次弹跳 ObjectAnimator bounceAnim2 = ObjectAnimator.ofFloat(starView, "y", finalY - 100, finalY - 50); bounceAnim2.setDuration(300); bounceAnim2.setInterpolator(new DecelerateInterpolator()); // 组合动画:下落 + 弹跳 AnimatorSet fallBounceSet = new AnimatorSet(); fallBounceSet.playSequentially(fallAnim, bounceAnim1, bounceAnim2); // 心形动画监听器 fallBounceSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { animateStarsToHeartShape(starView, index, STAR_COUNT); // 使用固定总数 } }); fallBounceSet.start(); }, i * 600); // 控制每颗星星之间的延迟 } } private void animateStarsToHeartShape(ImageView star, int index, int totalStars) { // 获取屏幕中心坐标 float centerX = getResources().getDisplayMetrics().widthPixels / 2f; float centerY = getResources().getDisplayMetrics().heightPixels / 2f; // 调整该值来控制心形的大小 float scale = 15f; // 调整t的计算方法,使得心形平滑 double t = Math.PI * 2 * index / totalStars; // 使用心形方程来生成心形的点 double heartX = 16 * Math.pow(Math.sin(t), 3); double heartY = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t); // 归一化 + 缩放 + 居中 float targetX = (float) (heartX * scale + centerX); float targetY = (float) (-heartY * scale + centerY); // y轴方向翻转 // 设置星星的初始位置到目标位置,不再进行动画移动 star.setX(targetX); star.setY(targetY); // 缩放动画(星星逐渐缩小) ObjectAnimator scaleX = ObjectAnimator.ofFloat(star, "scaleX", 1.5f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(star, "scaleY", 1.5f, 1f); // 旋转动画(星星飞行过程中有旋转效果) ObjectAnimator rotate = ObjectAnimator.ofFloat(star, "rotation", 0f, 360f); // 动画集合 AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(scaleX, scaleY); // 设置动画的持续时间和延迟 animatorSet.setDuration(800); animatorSet.setStartDelay(index * 20L); // 使得星星逐渐填充 animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.start(); } }我想在这个页面添加一首歌进行播放,可以实现这个三个每个页面跳转之后继续播放吗
07-15
任务描述 本关任务:写一个HBase的MapReduce任务。 相关知识 为了完成本关任务,你需要掌握: 编写自己的MapReduce。 编写自己的MapReduce HBase结合MapReduce可以实现从HBase输入表到HBase输出表、从文件到HBase输出表、从HBase输入表到文件的几种场景。 下面我们来完成一个从HBase输入表到HBase输出表的需求:从HBase表里统计列族comment_info中列名content的字符串单词的出现次数,并把统计结果存到HBase列族为word_info,列名为count的另一个表里。 我们分析一下需求,统计的是字符串中单词的个数,则key应该为Text类型,value 为IntWritable类型,输入表名为args[0]。Map节点配置如下: String tablename = args[0]; String targetTable = args[1]; Scan scan = new Scan(); Job job = Job.getInstance(conf); TableMapReduceUtil.initTableMapperJob(tablename,scan,MyMapper.class, Text.class, IntWritable.class,job); Map节点的目的是切分字符串,获取单词名称,把单词名称当做key值,单词数1当成value值,写到context.write(key,value)方法中,Map方法如下: public class MyMapper extends TableMapper<Text, IntWritable> { private static byte[] family = "comment_info".getBytes(); private static byte[] column = "content".getBytes(); @Override protected void map(ImmutableBytesWritable rowKey, Result result, Context context) throws IOException, InterruptedException { byte[] value = result.getValue(family, column); String content = new String(value,"utf-8"); String[] split = content.split(","); for(String str : split) { Text text = new Text(str); IntWritable v = new IntWritable(1); context.write(text,v); } } } } 接下来我们配置及使用 Reduce 方法,输出表名为args[1], Reduce节点配置如下 TableMapReduceUtil.initTableReducerJob(args[1],MyReducer.class,job); 由于Reduce节点需要把统计结果放到Mutation中,而Mutation是个抽象类,一般都会使用继承它的Put类,进行数据写入,Reduce节点的使用方法如下: public class MyReducer extends TableReducer<Text, IntWritable, ImmutableBytesWritable> { private static byte[] family = "word_info".getBytes(); private static byte[] column = "count".getBytes(); @Override public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException { int sum = 0; for (IntWritable value : values) { sum += value.get(); } Put put = new Put(Bytes.toBytes(key.toString())); put.addColumn(family,column,Bytes.toBytes(sum)); context.write(null,put); } 最后提交任务,并阻塞等待job执行完成: job.waitForCompletion(); 至此你就做完了你的第一个HBase的MapReduce任务啦! 编程要求 根据提示,在右侧Begin - End区域内补充代码,完成一个从文件到HBase输出表的需求:使用MapReduce统计单词个数。 String[] args数组,第一个参数为输入文件, 第二个参数为输出表 输入文件内容如下: There will be no regret and sorrow if you fight with all your strength give a stranger one of your smiles. It might be the only sunshine he sees all day Victory belongs to the most persevering The world is his who enjoys it want it more that anything Love is the greatest refreshment in life The first step is as good as half over My heart is with you Cease to struggle and you cease to live He knows most who speaks least Until you make peace with who you are, you’ll never be content with what you have One needs 3 things to be truly happy living in the world: some thing to do, some one to love, some thing to hope for I lied when I said I didn’t like you. I lied when I said I didn’t care. I lie every time I try to tell myself I will never fall for you 统计文件内容里出现的单词个数,并把统计结果保存到列族为word_info,单词个数为count的字段,单词名称为rowkey的输出表里。 测试说明 补充完代码后,点击测评,平台会对你编写的代码进行测试,当你的结果与预期输出一致时,即为通过。 测试输入:t_comment t_word_count; 预期输出: word:I word_info:count 9 word:be word_info:count 4 word:is word_info:count 4 word:the word_info:count 4 word:to word_info:count 8 word:with word_info:count 4 word:you word_info:count 7
10-31
你想要在第一个条件中**遍历整个 `mCurrentNetworkInfo`** 列表并判断每个元素是否满足 `it.ssid == info.ssid && it.mac == info.mac`,并且执行某些操作,当前使用的是: ```kotlin mCurrentNetworkInfo.filter { it.ssid == info.ssid && it.mac == info.mac } -> { ``` 但 `when` 条件语句中直接使用 `filter` 是不合适的,因为 `filter` 返回的是一个列表,而 `when` 的条件应是一个布尔表达式。 如果你想判断是否存在符合条件的元素,并且还想**遍历所有匹配的元素**进行操作,可以将逻辑拆分为如下结构: ### ✅ 正确实现方式 ```kotlin private fun setNetworksWeight() { val saved = AppDataBase.getInstance(application).extenderNetworkDao().all for (info in mHostNetworkList) { val matchedNetworks = mCurrentNetworkInfo.filter { it.ssid == info.ssid && it.mac == info.mac } if (matchedNetworks.isNotEmpty()) { // 遍历所有匹配的 mCurrentNetworkInfo 元素 for (network in matchedNetworks) { // 执行你想对每个匹配项的操作 info.weight = REHostNetworkInfoBean.Weight.CONNECTED info.password = network.password } } else if (saved.any { it.ssid == info.ssid && info.weight != REHostNetworkInfoBean.Weight.CONNECTED }) { info.weight = REHostNetworkInfoBean.Weight.MERCUSYS_SAVE info.password = saved.find { it.ssid == info.ssid }?.password } else if (TPWifiManager.getInstance().isWifiConnected(info.ssid)) { info.weight = REHostNetworkInfoBean.Weight.USER_SAVE } else if (info.oneMesh != null) { info.weight = REHostNetworkInfoBean.Weight.ONE_MESH } else { info.weight = REHostNetworkInfoBean.Weight.NORMAL } } } ``` 这样就能确保: - `matchedNetworks` 包含了所有满足条件的元素; - 使用 `for` 遍历 `matchedNetworks`,对每个匹配项执行操作; - 不会多次重复查找(避免使用 `find` 多次)。 --- ### ✅ 小结 - `find`:返回第一个匹配项; - `filter`:返回所有匹配项的列表; - 如果你希望对所有匹配项执行操作,就需要用 `filter` + `for` 遍历。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值