【问题标题】:How to pass a value from a runnable thread once it has finished in Android Studio?在 Android Studio 中完成后如何从可运行线程传递值?
【发布时间】:2021-08-20 21:36:16
【问题描述】:

我正在使用一个线程从我的数据库中获取一个 id。一旦线程完成运行,我需要在另一个线程中使用该 id 来获取项目列表。一旦该线程完成,我将使用项目列表来填充微调器。我遇到的问题是它在线程返回项目列表之前填充微调器。我怎样才能使它在线程完成运行之前不会填充微调器?

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

                new Thread(new Runnable() {
                    @Override
                    public void run() {

                        String bookName = existingBooks.get((int) spinner.getSelectedItemId());

                        Book myBook = AppDatabase.getInstance(getContext()).bookDAO().getBookByTitle(bookName);

                        long book_Id = myBook.getBook_id();

                        existingCountDates = AppDatabase.getInstance(getContext()).countDAO().getCountDatesInBook(book_Id);

                        List<Count> Counts = AppDatabase.getInstance(getContext()).countDAO().getAllCounts();

                        Log.e("Dates", existingCountDates.toString());
                        Log.e("All Counts", Counts.toString());

                    }
                }).start();

                //TODO: FIX THIS ISSUE
                Log.e("Problem:", "This gets called before the thread finishes. Not sure how to fix it");
                str_adapter.clear();
                for (int i = 0; i < existingCountDates.size(); i++) {
                    str_adapter.add(existingCountDates.get(i));
                }
                str_adapter.notifyDataSetChanged();

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {
                //TODO: DISABLE OTHER DROPDOWN MENUS?
            }
        });

【问题讨论】:

    标签: java android multithreading android-studio android-threading


    【解决方案1】:

    您可以使用另一个线程并等待前一个线程直到使用 thread.join() 完成。但更好的版本是使用ExecutorServices,例如ThreadPoolExecutor

    CODELAB

    【讨论】:

      【解决方案2】:

      我不确定这是否会对您有所帮助。但是你可以使用 bool 变量来检查线程是否完成了它的工作。

      bool flag = false;
      new Thread(new Runnable() {
          @Override
          public void run() {
              //statements
              flag = true;
          }
      }).start();
      while(flag != true);
      //statements to be executed after completion of thread.
      

      注意:确保执行永远不会进入无限循环。

      【讨论】:

      • 这帮助我弄清楚我真正的问题是什么。我也不知道如何将数据从线程传递到主 UI 线程。在使用您的代码之前,我没有意识到这是我不知道该怎么做的事情。所以谢谢!
      • 任何被线程改变的值都必须标记为volatile。此外,拥有while() 旋转循环也是一种非常糟糕的形式。我知道这是演示代码,但这类东西往往会被复制到工作项目中。
      【解决方案3】:

      我怎样才能使它在线程完成运行之前不会填充微调器?

      有几种方法可以做到这一点。最简单的方法可能是获得ExecutorService,这通常被推荐,而不是“手动”创建Thread。这也允许您从工作中返回一个值,在这种情况下您提交 Callable&lt;?&gt; 而不是 Runnable

      ExecutorService threadPool = Executors.newFixedThreadPool(1);
      ...
      Future<Void> future = threadPool.submit(new Runnable() {
          public void run() {
             ...
          }
      });
      // wait for this job to finish
      future.get();
      ...
      // when you are done with the pool you need to shut it down
      threadPool.shutdown();
      

      您也可以启动一个线程,然后用它join()。等待线程完成。

      Thread thread = new Thread(new Runnable() { ... });
      thread.start();
      // now we can do stuff while the thread runs in the background
      ...
      // wait for the thread to finish before returning
      thread.join();
      ...
      

      get() 方法或 join() 方法还意味着 existingCountDates 或在作业内部修改的任何其他内容将在调用者的内存中适当地更新。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-01
        • 2015-03-25
        • 2021-04-27
        • 1970-01-01
        • 1970-01-01
        • 2014-06-08
        • 1970-01-01
        • 2023-03-29
        相关资源
        最近更新 更多