与我之前关于ANR问题的问题(Android - Strings.xml versus text files. Which is faster?)相关。
我按照受访者的建议尝试使用AsyncTask,但我现在不知所措。
我需要将菜单活动中的字符串传递给Asynctask,但这真让我感到困惑。我已经搜索和学习了5个小时,但仍然无法做到。
以下是我的代码片段:
@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的东西应该在post执行时完成。 如果是这种情况,我应该在doInBackground()部分返回什么,然后传递onPostExecute()?
(非常感谢大家!我现在已经接近正常工作了!)
答案 0 :(得分:3)
这就是问题所在,它们是您声明它们的方法的本地方法,然后您声明了一个无法访问它们的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();
此外,您无法在UI
中执行doInBackground
内容,因此需要在Activity
类或Async
中的其他方法中进行更改onPostExecute()
这样的类,如果它是一个内部类。否则,您可以将值传回菜单活动以更新TextView
修改强>
您仍在尝试使用此
更改UI
中的doInBackground()
TextView databaseOutput1 = (TextView)findViewById(R.id.textView8);
然后再次致电setText()
。这需要放在onPostExecute()
中,但您需要将TextView
的引用传递给AsyncTask
。您可以从String
传回要设置文字的onPostExecute()
,并将其设置在Activity
中。希望这有帮助
答案 1 :(得分:1)
AsyncTaskRunner
课程创建构造函数。 Context
(您的活动上下文)和databaseOutput
TextView
作为参数传递给您的AsyncTaskRunner
类构造函数。AsyncTaskRunner
中保存对这两个对象的引用。enhancedStem
传递给execute()
方法。Context
作为ProgessDialog.show()
的第一个参数databaseOutput
方法访问doInBackground()
。您必须只能在UI线程上运行的onPostExecute()
中访问它。因此,使用您传递给构造函数的databseOutput
引用来相应地更新onPostExecute()
方法中的TextView。 作为备注,您可以使用doInBackground()
方法返回的任何内容作为onPostExecute()
方法的参数。
请参阅http://developer.android.com/reference/android/os/AsyncTask.html
我建议您传递所需的数据,而不是使用封闭的类访问它 - 这会使您的ASyncTaskRunner
更加灵活,通常是更好的做法。