Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我的值没有从内部类添加到全局ArrayList_Java_Android - Fatal编程技术网

Java 为什么我的值没有从内部类添加到全局ArrayList

Java 为什么我的值没有从内部类添加到全局ArrayList,java,android,Java,Android,我从服务器获取数据,并为每次循环执行创建类QuizFormat的对象。我声明了一个全局ArrayList,试图在其中添加这些对象。我在一个单独的方法getTest()中执行此任务,该方法具有内部类,并且它扩展了AsyncTask类,因为获取数据的后台任务是在该类中执行的。问题是,没有将对象添加到列表中。我尝试创建一个单独的方法,通过将对象作为参数传递来添加对象,但运气不好。我怎样才能解决这个问题?这是我正在使用的代码。 QuizFormat,一个包含构造函数、getter和setter的基本类:

我从服务器获取数据,并为每次循环执行创建类
QuizFormat
的对象。我声明了一个全局
ArrayList
,试图在其中添加这些对象。我在一个单独的方法
getTest()
中执行此任务,该方法具有内部类,并且它扩展了
AsyncTask
类,因为获取数据的后台任务是在该类中执行的。问题是,没有将对象添加到列表中。我尝试创建一个单独的方法,通过将对象作为参数传递来添加对象,但运气不好。我怎样才能解决这个问题?这是我正在使用的代码。
QuizFormat
,一个包含构造函数、getter和setter的基本类:

公共类QuizFormat{
int-id;
字符串问题;
字符串[]选项;
字符串回答;
公共QuizFormat(int-id、字符串问题、字符串[]选项、字符串答案){
this.id=id;
这个问题=问题;
this.options=选项;
这个答案=答案;
}
//下面是接受者和接受者
...
...
}
以下是
TestActivity
类,我在其中执行上述所有任务:

公共类测试活动扩展了AppCompative活动{
ArrayList quizFormatList;//全局ArrayList
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_测试);
quizFormatList=新建ArrayList();//初始化ArrayList
getTest();//调用方法获取和添加元素
//检查最终尺寸
Log.i(“size”,“ArrayList:+quizFormatList.size());
试一试{
for(QuizFormat qf:quizFormatList){
Log.i(“que”,qf.getQuestion());
}
}捕获(NullPointerException e){
e、 printStackTrace();
}
}
公共无效getTest(){
类FetchData扩展异步任务{
@凌驾
受保护的void onPostExecute(字符串s){
super.onPostExecute(s);

对于(int i=0;i这是一个典型的异步与同步行为问题。这里发生的是,您正在调用方法
getTest
,该方法是异步的,并在
quizFormatList
之后访问。问题是在
getTest
有机会填充它之前访问
quizFormatList
。难忘不幸的是,这样做是不可能的,而且有时可能有效,有时可能无效

有几种解决方案,让我尝试并提供一种不需要对现有内容进行太多更改的解决方案。首先,我们希望异步任务在完成其工作时实际通知主活动。我们将通过回调完成此操作:

interface OnAsyncWorkDoneCallback {
  void asyncWorkDone(List<QuizFormat> quizFormatList);
}

class FetchData extends AsyncTask<Void,Void,String> {
  private final List<QuizFormat> quizFormatList = new ArrayList<>();
  private final OnAsyncWorkDoneCallback callback;

  public FetchData(OnAsyncWorkDoneCallback callback) {
    this.callback = callback;
  }

  @Override
  protected void onPostExecute(String s) {
    // Do exactly what you were doing before and populate the field quizFormat

    callback.asyncWorkDone(quizFormatList);
  }
}


上面的代码有望工作并满足您的需求,但我必须说,在android上使用异步任务被认为是危险的,并且非常不鼓励。这个主题本身就是另一个完整的答案,我现在不想讨论它,因为您的问题不一定特定于异步任务,而是异步环境中的竞争条件不过,你可以看到,如果主要活动被破坏(手机旋转,即)传递给当前正在运行的异步任务的回调将属于已销毁的活动,并且取决于您对结果所做的操作,它可能最终尝试访问它无法再访问的内容。这只是此方法的问题之一。您可以联机阅读所有内容,关于它的信息已经足够多,但下面是一个示例Dan Lew做得非常好。

可能是因为同步性。你调试过代码了吗,以检查所有操作的执行顺序?@Stultuske是的,我只是检查了一下,想知道完整的
onCreate()
方法是先执行的,而方法
getTest()是先执行的
正在稍后执行,这就是它可能导致的原因。但是有什么解决方案吗?确实如此。您在onCreate结束时启动了异步任务。由于onCreate在另一个线程中运行,onCreate早就在doInBackground开始之前结束了,但您在onPostExecute中所做的一切都是正常的。但是……我看不到doInBackground…@blackapps,但我要使用该列表中的对象执行进一步的任务。我可以从
onCreate()
方法访问它们吗?有解决方案吗?好的。如果要使用该列表,请在onPostExecute中执行。可以在onPostExecute中只调用活动中执行该任务的函数。将所有代码放在函数checkSize()中的
//checking final size
之后并在onPostExecute中调用它。感谢您提供的有用信息。好吧,我必须寻找另一种方法,因为在设备旋转的情况下,这可能会破坏预期的任务。但感谢您的帮助。
I/size: ArrayList: 0
interface OnAsyncWorkDoneCallback {
  void asyncWorkDone(List<QuizFormat> quizFormatList);
}

class FetchData extends AsyncTask<Void,Void,String> {
  private final List<QuizFormat> quizFormatList = new ArrayList<>();
  private final OnAsyncWorkDoneCallback callback;

  public FetchData(OnAsyncWorkDoneCallback callback) {
    this.callback = callback;
  }

  @Override
  protected void onPostExecute(String s) {
    // Do exactly what you were doing before and populate the field quizFormat

    callback.asyncWorkDone(quizFormatList);
  }
}
public class TestActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_test);

    new FetchData((results) -> {
        // do whatever you need to do with results
    }).execute();
  }   
}