【问题标题】:How to store lots of data upon Screen Rotation?如何在屏幕旋转上存储大量数据?
【发布时间】:2019-01-18 17:00:48
【问题描述】:

是的,我已经阅读了许多其他帖子,但我无法继续跟进,因为我有很多变数,而不仅仅是一两个。

我第一次制作了一个带有横向支持的应用程序(TIC TAC TOE)。我正在丢失有关屏幕旋转的数据。

package com.netlify.krupesh.tictactoe;

import android.graphics.Typeface;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    // 0 for zero and 1 for X
    // 2 for empty
    boolean gameActive = true;
    int[] gameState = {2,2,2,2,2,2,2,2,2};
    int[][] winningPositions = {{0,1,2}, {3,4,5}, {6,7,8}, {0,3,6}, {1,4,7}, {2,5,8}, {0,4,8}, {2,4,6}};

    int activePlayer = 0;
    int[] playerScores = {0,0};

    // Show Symbol on Tap
    public void showSymbol(View view){
        // Set Player Scores
        TextView player1 = (TextView) findViewById(R.id.p1Score);
        TextView player2 = (TextView) findViewById(R.id.p2Score);


        player1.setText(playerScores[0]+"");
        player2.setText(playerScores[1]+"");

        // Get Symbol Info
        ImageView symbol = (ImageView) view;
        int tappedSymbol = Integer.parseInt(symbol.getTag().toString());

        // Update Game state Array
        if(gameState[tappedSymbol]==2 && gameActive) {
            gameState[tappedSymbol] = activePlayer;

            // Show Symbol with Animation
            symbol.setAlpha(0f);
            if (activePlayer == 0) {
                symbol.setImageResource(R.drawable.zero);
                activePlayer = 1;
                showCurrentPlayer(2);

            } else {
                symbol.setImageResource(R.drawable.cross);
                activePlayer = 0;
                showCurrentPlayer(1);
            }
            symbol.animate().alpha(1).setDuration(400);

            checkDraw(gameState);

            for (int[] winningPosition : winningPositions) {
                if (gameState[winningPosition[0]] == gameState[winningPosition[1]] && gameState[winningPosition[1]] == gameState[winningPosition[2]] && gameState[winningPosition[0]] != 2) {
                    showCurrentPlayer(0);
                    // Pause The Game
                    gameActive = false;

                    // Won the Game
                    String winningPlayer ;
                    if (gameState[winningPosition[0]] == 0) winningPlayer = "Player 1";
                    else winningPlayer = "Player 2";
                    Toast.makeText(this, winningPlayer + " won!", Toast.LENGTH_SHORT).show();

                    // Update Scores
                    playerScores[gameState[winningPosition[0]]]++;
                    player1.setText(playerScores[0] + "");
                    player2.setText(playerScores[1] + "");
                }
            }
        }
    }


    public void resetBoard(View view){
        android.support.v7.widget.GridLayout board = (android.support.v7.widget.GridLayout)findViewById(R.id.gridLayout);
        for(int i=0; i<board.getChildCount(); i++) {
            ImageView symbol = (ImageView) board.getChildAt(i);
            symbol.setImageDrawable(null);
        }
        for(int i=0; i<gameState.length; i++ ){
            gameState[i] = 2;
        }
        gameActive = true;
        activePlayer = 0;
        showCurrentPlayer(1);
    }

    public void checkDraw(int[] gamestate){
        for(int i =0; i<gamestate.length; i++){
            if(gamestate[i]==2){
                return;
            }
        }
        showCurrentPlayer(0);
        Toast.makeText(this, "Match Draw!", Toast.LENGTH_SHORT).show();
    }

    public void resetAll(View view){
        resetBoard(view);
        playerScores[0]=0; playerScores[1]=0;
        TextView player1 = (TextView) findViewById(R.id.p1Score);
        TextView player2 = (TextView) findViewById(R.id.p2Score);
        player1.setText(playerScores[0] + "");
        player2.setText(playerScores[1] + "");
        showCurrentPlayer(1);
    }

    public void showCurrentPlayer(int i){
        TextView player1Heading = (TextView) findViewById(R.id.subheading1);
        TextView player2Heading = (TextView) findViewById(R.id.subheading2);
        if(i==1){
            player1Heading.setTextColor(getResources().getColor(R.color.colorPlayer1));
            player1Heading.setTypeface(null, Typeface.BOLD);
            player2Heading.setTextColor(getResources().getColor(R.color.colorHeading));
            player2Heading.setTypeface(null, Typeface.NORMAL);
        }
        if(i==2){
            player2Heading.setTextColor(getResources().getColor(R.color.colorPlayer2));
            player2Heading.setTypeface(null, Typeface.BOLD);
            player1Heading.setTextColor(getResources().getColor(R.color.colorHeading));
            player1Heading.setTypeface(null, Typeface.NORMAL);
        }
        if(i==0){
            player1Heading.setTextColor(getResources().getColor(R.color.colorHeading));
            player1Heading.setTypeface(null, Typeface.NORMAL);
            player2Heading.setTextColor(getResources().getColor(R.color.colorHeading));
            player2Heading.setTypeface(null, Typeface.NORMAL);
        }
    }



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ===================== Hide Status Bar ========================== //
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        // ================================================================ //

        setContentView(R.layout.activity_main);
        showCurrentPlayer(1);
    }
}

看,有很多东西.. 对于所有 ImageViews,我需要保存设置了图像的人。现在我该如何解决这个旋转问题??

添加代码片段的解决方案是最有帮助的,Android 开发新手

【问题讨论】:

  • Use ViewModel。或者,使用保存的实例状态Bundle
  • 对我来说就像希腊语和拉丁语,你能分享一个代码片段吗,PLeaseeee.@CommonsWare
  • 我建议你花时间去实际学习材料,而不是仅仅依靠随机代码sn-ps。阅读涵盖这些主题的书。或者,参加涵盖这些主题的课程(直播、Udacity 视频等)。
  • 是的,当然。我从 udacity 为 android 初学者做了 2 门课程,我可以创建一个漂亮的 UI Tic Tac Toe,功能齐全。只是在 Playstore 中推出了几个波兰语.. 我总是可以继续学习..
  • 太棒了!如果那是 Google 的官方课程,它应该涵盖 ViewModel 或保存的实例状态 Bundle。如果您说这些课程都没有涵盖任何主题……那表明这些课程很糟糕。虽然ViewModel 相对较新,但保存的实例状态Bundle 从一开始就与我们同在。

标签: android screen-rotation


【解决方案1】:

@krupesh Anadkat 作为一个新手,我感到很沮丧,但 @CommonsWare 是一位经验丰富的开发人员,已经在游戏中工作了好几天。

听从他的建议,确保你了解他概述的基本原理,而不是为了它而匆匆完成或匆忙构建一些东西。

但是今天是你的幸运日,所以我会用一些代码 sn-ps 来宠爱你(我们千禧一代的程序员喜欢它,是的,我说过了!!!)阅读 youngling 并学习。

您在此处面临的问题是设备配置更改。

在您的情况下,屏幕方向发生了变化。

用户每次旋转屏幕时,Android 操作系统都会重新创建一个新的活动Android 操作系统意味着它只是试图提高效率,因为它检查是否有更好的资源用于新的方向,如果有,它可以使用这些资源。

这是你痛苦的根源。现在让我们一起破解并帮助你吧。

您可以使用 Activity 的 类方法来解决这个问题。在万能的 Android OS 杀死您的 Activity 之前,方法 onSaveInstanceState() 将在您的 Activity 生命周期中被调用。在您的课程中,您覆盖 onSaveInstanceState() 并将您想要的数据保存到 onSaveInstanceState() 作为参数的 Bundle

然后在 Activity 的 onCreate() 中检查 savedInstanceState 是否不为空,如果它不为空,则您检索数据。

不过要小心;最好将 原始数据类型 保存到 Bundle可序列化 的对象中,以避免检索过时或无效的数据没有了。

请参阅下面我的 SaveDataAcrossScreenOrientation Activity 的代码 sn-p

package com.demo.android.savedataacrossscreenrotationdemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class SaveDataAcrossScreenOrientation extends AppCompatActivity {

    // Key to be used for the key: value pair to be saved to the bundle
    private static final String KEY_GREETING_TEXT = "greeting_text";

    // The text currently displayed to the screen
    private String mCurrentDisplayedText;

    private TextView mGreetingTextView;
    private Button mSpanishButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Get references to the button and textview
        mGreetingTextView = (TextView) findViewById(R.id.greeting_text_view);
        mSpanishButton = (Button) findViewById(R.id.change_greeting_button);

        // If mCurrentDisplayedText is inside the bundle retrieve and display it on screen
        if(savedInstanceState != null) {
            mCurrentDisplayedText = savedInstanceState.getString(KEY_GREETING_TEXT, "");
            if (mCurrentDisplayedText != "") {
                mGreetingTextView.setText(mCurrentDisplayedText);
            }
        }

        // Set a listener on the spanish button
        mSpanishButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // Change the english text to spanish when the button is clicked
                mGreetingTextView.setText(R.string.spanish_greeting);

                // Get the text currently shown in the text view
                mCurrentDisplayedText = (String) mGreetingTextView.getText(); // Calling getText() returns a CharSequence cast it to a string
            }
        });
    }

    // Override onSaveInstanceState(Bundle savedInstanceState) and save mCurrentDisplayedText to the bundle
    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putString(KEY_GREETING_TEXT, mCurrentDisplayedText);
    }

}

See video demo here

玩得开心!

【讨论】:

  • 您在此处发布的代码 sn-p 已在另一个 stackoverflow 中。
  • 除了一些行之外,我也在其他几个地方读过同样的概念。无论如何,感谢和抱歉让您感到痛苦,我已经在 Google Playstore 中发布了我的应用程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-12
相关资源
最近更新 更多