在Java中,如果在局部变量范围之外使用,列表将显示为null

在Java中,如果在局部变量范围之外使用,列表将显示为null,java,android,Java,Android,背景:我正在创建一个基于turnbased的多人游戏。该用户与另一个用户随机匹配。匹配后,用户会得到一个单词列表,他需要使用这些单词来提醒游戏。这个单词列表是从一个更大的列表中随机选择的 问题:我在运行应用程序时遇到索引越界异常(异常指向查询外部使用mCopy的行。getFirstInBackground代码块。当我调试应用程序并在mCopy上设置断点时(用户可用的单词列表),它显示了一个空列表。应该注意的是,wordsList出现在后端,如果我执行查询中的所有代码。getFirstInBack

背景:我正在创建一个基于turnbased的多人游戏。该用户与另一个用户随机匹配。匹配后,用户会得到一个单词列表,他需要使用这些单词来提醒游戏。这个单词列表是从一个更大的列表中随机选择的

问题:我在运行应用程序时遇到索引越界异常(异常指向
查询外部使用
mCopy
的行。getFirstInBackground
代码块。当我调试应用程序并在
mCopy
上设置断点时(用户可用的单词列表),它显示了一个空列表。应该注意的是,wordsList出现在后端,如果我执行
查询中的所有代码。getFirstInBackground
块,我没有问题。但是,我想要的是,一旦
mCopy
从Parse中检索列表,我就可以在类中的任何位置使用mCopy

以下是相关代码:

public class PlayGameActivity extends Activity {
    protected LinkedList<String> mCopy; //This is a global variable where words are stored


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

        mCopy = new LinkedList<String>();

        Intent cameFromGIPActivity = getIntent();
        mCameFromGIPActivity = cameFromGIPActivity.getStringExtra(ExTRA_GamesInProgress);

        // if this is null, that means opp came from FindingOpp Activity
        if (mCameFromGIPActivity == null) {

            //use the opponent name as a key to get selected words(value)
            ParseQuery<ParseObject> query = ParseQuery.getQuery(ParseConstants.CLASS_GAMES_IN_PROGRESS);
            query.whereMatches(ParseConstants.KEY_OPPONENT_NAME, mOpponentName);

            query.getFirstInBackground(new GetCallback<ParseObject>() {

                @Override
                public void done(ParseObject gameInfo, ParseException e) {
                    if (e == null) {
                        Log.d(TAG, "success!");

                        mSavedWordList = gameInfo.getString(ParseConstants.KEY_SELECTED_WORDS);
                        Gson gson = new Gson();
                        Type type = new TypeToken<ArrayList<String>>() {
                        }.getType();
                        ArrayList<String> finalWordList = gson.fromJson(mSavedWordList, type);
                        mCopy.addAll(finalWordList);
    });




         word1 = (TextView) findViewById(R.id.word1); //I get the index out of bound exception here,
         word1.setText(mCopy.get(1));
         word1.setOnClickListener(new View.OnClickListener());
公共类PlayGameActivity扩展活动{
受保护的LinkedList mCopy;//这是存储单词的全局变量
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity\u play\u game);
mCopy=newlinkedlist();
Intent cameFromGIPActivity=getIntent();
mCameFromGIPActivity=cameFromGIPActivity.getStringExtra(ExTRA_GamesInProgress);
//如果为空,则表示opp来自FindingOpp活动
if(mCameFromGIPActivity==null){
//使用对手名称作为键以获取所选单词(值)
ParseQuery query=ParseQuery.getQuery(ParseConstants.CLASS\u GAMES\u进行中);
query.whereMatches(ParseConstants.KEY\u opporter\u NAME,mOpponentName);
getFirstInBackground(新的GetCallback(){
@凌驾
公共无效完成(ParseObject gameInfo,Parsee异常){
如果(e==null){
Log.d(标记“success!”);
mSavedWordList=gameInfo.getString(ParseConstants.KEY_SELECTED_WORDS);
Gson Gson=新的Gson();
Type Type=new-TypeToken(){
}.getType();
ArrayList finalWordList=gson.fromJson(mSavedWordList,类型);
mCopy.addAll(最终订单列表);
});
word1=(TextView)findViewById(R.id.word1);//我在这里得到了索引越界异常,
word1.setText(mCopy.get(1));
setOnClickListener(新视图.OnClickListener());
Edit1:我之前说过我在logCat中没有异常,我错了。我得到了绑定异常的索引。抱歉。

如上所述,
getFirstInBackground
根据您在单独线程中的查询检索
ParseObject
,而不阻止/冻结当前线程中的执行。一次提取完成后,调用回调对象中的
done()

尽管看起来您的语句在代码中是一个接一个地排序的,
getFirstInBackground
是一个异步操作。因此,fetch将在不同的线程中运行,而代码中的其余语句将被执行

由于您的
mCopy
是在
done
方法中更新的,因此任何依赖更新的代码都应该用如下相同的方法执行

    query.getFirstInBackground(new GetCallback<ParseObject>() {

               @Override
               public void done(ParseObject gameInfo, ParseException e) {
                    if (e == null) {
                         Log.d(TAG, "success!");

                         mSavedWordList = gameInfo.getString(ParseConstants.KEY_SELECTED_WORDS);
                         Gson gson = new Gson();
                         Type type = new TypeToken<ArrayList<String>>() {
                            }.getType();
                         ArrayList<String> finalWordList = gson.fromJson(mSavedWordList, type);
                         mCopy.addAll(finalWordList);
                         /* mCopy is updated here - so use it now*/
                         word1 = (TextView) findViewById(R.id.word1); 
                         word1.setText(mCopy.get(1));
                         word1.setOnClickListener(new View.OnClickListener());


    });
query.getFirstInBackground(新的GetCallback(){
@凌驾
公共无效完成(ParseObject gameInfo,Parsee异常){
如果(e==null){
Log.d(标记“success!”);
mSavedWordList=gameInfo.getString(ParseConstants.KEY_SELECTED_WORDS);
Gson Gson=新的Gson();
Type Type=new-TypeToken(){
}.getType();
ArrayList finalWordList=gson.fromJson(mSavedWordList,类型);
mCopy.addAll(最终订单列表);
/*mCopy在此处更新-所以现在就使用它*/
word1=(TextView)findViewById(R.id.word1);
word1.setText(mCopy.get(1));
setOnClickListener(新视图.OnClickListener());
});

如果在finalWordList创建后立即登录它,您会得到什么?在编辑时:我假设IndexOutOfBoundsException在mCopy上。get(1)行?如果是,这只是mCopy为空的一个症状,一旦解决了这个问题,IndexOutOfBoundsException应该消失,尽管检查mCopy是否为空是一个很好的做法,而不是假设它不是。为什么它不应该为空呢?如果
MCAMEFROMGIPATIVITY
不是
null
,它肯定是空的,因为不向其添加任何内容。如果
mCameFromGIPActivity
null
,则当您转到
word1.setText(mCopy.get(1))时,它可能为空;
因为您似乎只是在另一个线程中添加到它。是的,关于异常,您是绝对正确的。我知道mCopy是空的,当我在调试模式下运行应用程序时,它显示mCopy的大小为0。我不明白的是为什么会出现这种情况。此外,我无法在
finalWordList
或retr上设置断点请看日志声明。谢谢Paul,我想你和Arkantos说的是同一件事。有什么办法吗?这正是我现在让我的代码工作的方式。但是,因为有多个活动,用户可以从中输入
PlayGameActivity
,而且有很多词,我不希望我的代码变得如此简单bose,虽然似乎没有其他的解决方法?如果你有多个单词,为什么不在列表中循环设置onclick listener?应该