非Activity类更新TextView致应用崩溃,寻求技术解决方案
嗨,我一眼就看出问题出在哪啦!你在GameLogic里直接new了一个OnePlayerGameActivity的实例,这可是Android开发里的大忌啊!
为什么会崩溃?
Android的Activity是由系统负责实例化和管理生命周期的,你手动new OnePlayerGameActivity()出来的对象根本没有经过onCreate等生命周期方法,布局都没加载完成,findViewById(R.id.game_result_textView)自然会返回null,接着调用result.setText("LOST")就会触发NullPointerException,直接导致应用崩溃。
正确的解决方案:用接口回调解耦
咱们要把UI更新的逻辑交还给Activity本身,同时让GameLogic只负责处理游戏逻辑,通过接口回调的方式通知Activity更新TextView。具体步骤如下:
1. 定义游戏结果回调接口
可以在GameLogic类内部或者单独创建一个接口文件:
public interface GameResultListener { // 用来传递游戏结果文本的方法 void onGameResult(String resultText); }
2. 修改GameLogic类,持有接口引用而非Activity
把直接操作Activity和TextView的代码去掉,换成通过回调通知:
public class GameLogic { private GameResultListener mResultListener; private int mPlayerStat = 0; private int mOpponentStat = 0; private int mPlayerChoice; // 提供方法设置回调监听 public void setGameResultListener(GameResultListener listener) { mResultListener = listener; } public void gameResult() { getPlayerChoice(); int computer = computerChoice(); String resultText = ""; if (mPlayerChoice == computer) { mPlayerStat += 0; mOpponentStat += 0; resultText = "DRAW"; } else if (mPlayerChoice == 1) { // ROCK switch (computer) { case 2: // PAPER mOpponentStat++; resultText = "LOST"; break; case 3: // SCISSORS mPlayerStat++; resultText = "WIN"; break; } } // 这里可以补充其他玩家选择的逻辑(比如PAPER、SCISSORS的情况) // 游戏结果确定后,通过回调通知Activity更新UI if (mResultListener != null) { mResultListener.onGameResult(resultText); } } // 你的其他方法:getPlayerChoice()、computerChoice()等 private void getPlayerChoice() { // 你的实现逻辑 } private int computerChoice() { // 你的实现逻辑 return 0; } }
3. 在OnePlayerGameActivity中实现回调接口
在Activity里初始化TextView,并实现回调方法来更新UI:
public class OnePlayerGameActivity extends AppCompatActivity implements GameResultListener { private TextView mResultTextView; private GameLogic mGameLogic; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_game_activity_layout); // 替换成你的布局文件名 // 初始化TextView,这时候布局已经加载,findViewById不会返回null mResultTextView = findViewById(R.id.game_result_textView); // 初始化GameLogic并设置回调监听 mGameLogic = new GameLogic(); mGameLogic.setGameResultListener(this); } // 实现回调方法,在这里更新TextView @Override public void onGameResult(String resultText) { mResultTextView.setText(resultText); } // 比如在游戏结束的触发点调用gameResult()方法 public void triggerGameResult() { mGameLogic.gameResult(); } // 注意:Activity销毁时移除回调,避免内存泄漏 @Override protected void onDestroy() { super.onDestroy(); mGameLogic.setGameResultListener(null); } }
这样修改后,GameLogic只专注于游戏逻辑,UI更新的事情交给Activity处理,既避免了崩溃,又符合Android的架构规范,还能防止内存泄漏~
内容的提问来源于stack exchange,提问作者Matt
相关产品推荐
相关产品推荐

