【问题标题】:Android - Passing String to Asynctask?Android - 将字符串传递给 Asynctask?
【发布时间】:2013-02-15 03:35:33
【问题描述】:

与我之前关于 ANR 问题 (Android - Strings.xml versus text files. Which is faster?) 的问题有关。

我尝试按照受访者的建议使用 AsyncTask,但我现在不知所措。

我需要将一个字符串从我的菜单活动传递给 Asynctask,但这真的让我很困惑。我已经搜索和学习了 5 个小时,但仍然无法做到。

这是我的代码的 sn-p:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    /** Create an option menu from res/menu/items.xml */
    getMenuInflater().inflate(R.menu.items, menu);

    /** Get the action view of the menu item whose id is search */
    View v = (View) menu.findItem(R.id.search).getActionView();

    /** Get the edit text from the action view */
    final EditText txtSearch = ( EditText ) v.findViewById(R.id.txt_search);

    /** Setting an action listener */
    txtSearch.setOnEditorActionListener(new OnEditorActionListener() {

        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

            final EditText txtSearch = ( EditText ) v.findViewById(R.id.txt_search);
            String enhancedStem = txtSearch.getText().toString();
            TextView databaseOutput = (TextView)findViewById(R.id.textView8);

            new AsyncTaskRunner().execute();
            // should I put "enhancedStem" inside execute?
            }
          });
return super.onCreateOptionsMenu(menu);
}

这是异步部分:已更新

public class AsyncTaskRunner extends AsyncTask<String, String, String> {
      String curEnhancedStem;
      private ProgressDialog pdia;

      public AsyncTaskRunner (String enhancedStem)
      {
           this.curEnhancedStem = enhancedStem;
      }

      @Override
      protected void onPreExecute() {
       // Things to be done before execution of long running operation. For
       // example showing ProgessDialog
          super.onPreExecute();
          pdia = ProgressDialog.show(secondactivity.this, "" , "Searching for words");
      }



    @Override
    protected String doInBackground(String... params) {

        if(curEnhancedStem.startsWith("a"))
        {
            String[] wordA = getResources().getStringArray(R.array.DictionaryA);
            String delimiter = " - ";
            String[] del;
            TextView databaseOutput1 = (TextView)findViewById(R.id.textView8);
            for (int wordActr = 0; wordActr <= wordA.length - 1; wordActr++)
            {
                String wordString = wordA[wordActr].toString();
                del = wordString.split(delimiter);

                if (curEnhancedStem.equals(del[0]))
                {
                    databaseOutput1.setText(wordA[wordActr]);
                    pdia.dismiss();
                    break;
                }
                else
                    databaseOutput1.setText("Word not found!");
            }
        }

       return null;
      } 


      @Override
      protected void onProgressUpdate(String... text) {
       // Things to be done while execution of long running operation is in
       // progress. For example updating ProgessDialog

      }

      @Override
      protected void onPostExecute(String result) {
       // execution of result of Long time consuming operation
      }
}

现在可以检索了。我看到它显示正在寻找的单词,但它突然终止了。 也许是因为,就像你提到的那样,UI 的东西应该在执行后完成。 如果是这种情况,我应该在 doInBackground() 部分返回什么,然后传递 onPostExecute()?

(非常感谢大家!我现在已经接近正常工作了!)

【问题讨论】:

  • 我根本不是想成为一个杀手,但这段代码确实离正常工作还差得远。从 doInBackground 方法内部对 textView 的引用将失败。除了从 UI 线程之外,您无法触摸 UI。我确定这不是您想听到的,但是,既然您对这些东西的工作原理有了更多了解,您可能想暂停一下,阅读 Android 架构,然后重新开始。
  • 是的!我已经阅读并研究了一些关于 Asynctask 的内容,并且该问题已经得到解决。谢谢你的提醒! :)

标签: android string android-asynctask parameter-passing


【解决方案1】:

这就是问题所在,它们在您声明它们的方法中是本地的,然后您声明了一个无权访问它们的 AsyncTask 类。如果AsyncTask 是菜单活动的内部类,那么您可以将它们声明为成员变量。

public class MenuActivity extends Activity
{
     String enhancedStem;
     ....

如果它是一个单独的类,那么您可以在 Async 类中创建一个构造函数并将变量传递给构造函数。

public class AsyncTaskRunner extends AsyncTask<String, String, String> {
  String curEnhancedStem;
  private ProgressDialog pdia;

  public void AsyncTaskRunner (String variableName)
{
     this.curEnhancedStem = variableName;
}

然后这样称呼它

 AsyncTaskRunner newTask = new AsyncTaskRunner(enhancedStem);
 newTask.execute();

另外,你不能在doInBackground 中做UI 的东西,所以这需要在Activity 类或Async 类中的其他方法之一中进行更改,例如onPostExecute(),如果它是一个内部类。否则,您可以将值传回菜单活动以更新您的TextView

编辑

您仍在尝试使用此更改doInBackground() 中的UI

TextView databaseOutput1 = (TextView)findViewById(R.id.textView8);

然后当您致电setText() 时再次。这需要放在您的onPostExecute() 中,但是您需要将TextView 的引用传递给AsyncTask。您可以将想要将文本设置为来自onPostExecute()String 传回,并将其设置在Activity 中。希望这会有所帮助

【讨论】:

  • 我同意第二部分(在您到达 onPostExecute 之前不访问 UI 元素),但我认为第一部分有点误导。您可以通过我在答案中显示的语法访问该类的私有变量。
  • 如果它被声明为方法的局部变量,则不会。如果它是类的成员变量,你可以
  • 嗯,是的。但如果它是方法的局部变量,您当然可以让调用类的变量公开可见(这将是可怕的设计,但我离题了)。
  • @DigCamara 如果在方法中声明它们,则不能将它们公开。他们仍然必须有类范围
  • 嗨!我进行了更新,现在可以使用了!非常感谢。但在屏幕上显示单词的定义后,它会强制关闭。
【解决方案2】:
  1. 为您的AsyncTaskRunner 类创建一个构造函数。
  2. Context(您的活动上下文)和databaseOutput TextView 作为参数传递给您的AsyncTaskRunner 类构造函数。
  3. AsyncTaskRunner 中保存对这两个对象的引用。
  4. enhancedStem 传递给execute() 方法。
  5. 使用您传递给构造函数的Context 作为ProgessDialog.show() 的第一个参数
  6. 您无法通过doInBackground() 方法访问databaseOutput。您只能在onPostExecute() 中访问它,它在 UI 线程上运行。因此,使用您传递给构造函数的对databseOutput 的引用来相应地更新onPostExecute() 方法中的TextView。

请注意,您从doInBackground() 方法返回的任何内容都将作为onPostExecute() 方法的参数提供给您。

请参考http://developer.android.com/reference/android/os/AsyncTask.html

我建议您传递所需的数据,而不是使用封闭类访问它 - 这使您的 ASyncTaskRunner 更加灵活,并且通常是更好的做法。

【讨论】:

  • 感谢泰勒的创意!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
相关资源
最近更新 更多