1

在我的 android 应用程序中单击按钮时,我必须做一项大任务,所以我使用 runnable 来做后台工作。我的工作很好,没有使用可运行但大任务冻结了一段时间。使用 runnable 后,我的应用程序在单击按钮时崩溃。这是我的按钮 onClick 函数代码:

 public void doSearch(View v)
{
    EditText et1 = (EditText) findViewById(R.id.searchText);
    String query = et1.getText().toString();
    Toast.makeText(this, "Searching Lyrics for "+query, Toast.LENGTH_LONG).show();
    final String query1 = query.replaceAll(" ", "+");
    Runnable myRunnable = new Runnable() {
        @Override
        public void run(){
            try{
                HttpClient httpclient = new DefaultHttpClient();
                HttpGet httpget = new HttpGet("http://example.com/search.php?q="+query1);
                HttpResponse response = httpclient.execute(httpget);
                HttpEntity entity = response.getEntity(); 
                InputStream is = entity.getContent();
                BufferedReader reader = new BufferedReader(new InputStreamReader(is, "iso-8859-1"), 8);
                String line = null;
                int count=0,counter=0, disCount=0;
                String[] name = new String[20];
                String[] link = new String[20];
                String[] dis = new String[20];
                while ((line = reader.readLine()) != null && counter<20){
                    if(count == 1){
                        if(line.contains("href=\"")){
                            line = line.substring(line.indexOf('=')+2);
                            link[counter] = line.substring(0, line.indexOf('"'));
                            line = line.substring(line.indexOf('"')+2);
                            name[counter] = line.substring(0, line.indexOf('<'));
                        }
                        if(disCount==1){
                            if(line.contains("<b>")){
                                line = line.replaceAll("<b>", "");
                            }
                            if(line.contains("</b>")){
                                line = line.replaceAll("</b>", "");
                            }
                            dis[counter] = line+"...";
                            counter++;
                            disCount=0;
                        }
                    }
                    if(line.equals("<div class=\"sen\">")){
                        count = 1;
                    }
                    if(line.equals("<div>")){
                        disCount=1;
                    }
                    if(line.equals("</div>")){
                        count = 0;
                    }
                }
                is.close();
line 82:            searchResult(name, link, dis);
            }catch(IOException e){} catch(IllegalStateException e){}
        }
    };
    Thread myThread = new Thread(myRunnable);
    myThread.start();
}

public void searchResult(String[] name, String[] link, String[] dis)
{
   line 91:     setContentView(R.layout.results);
    nameTemp = name;
    linkTemp = link;
    rowItems = new ArrayList<RowItem>();
    for (int i = 0; i < name.length; i++) {
        if(name[i]==null) break;
        if(name[0]==null){
            Toast.makeText(this, "Sorry! No results matched your query. \n Try again! ", Toast.LENGTH_LONG).show();
            }
        RowItem item = new RowItem(name[i], dis[i]);
        rowItems.add(item);
    }

    listView = (ListView) findViewById(R.id.result);
    CustomListViewAdapter adapter = new CustomListViewAdapter(this, R.layout.list_item, rowItems);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(this);
}

@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
    Toast.makeText(this, "Loading Lyrics for "+nameTemp[position]+"!", Toast.LENGTH_SHORT).show();
    Intent i = new Intent(this, ShowLyricsActivity.class);
    i.putExtra("link", linkTemp[position]);
   startActivity(i); 
}

这是我的日志:

 I/ActivityManager(15444): Starting activity: Intent { act=android.intent.action.MAIN flg=0x10100000 cmp=com.BoxscapeInc.SongLyrics/.MainActivity }
 V/ActivityThread(28108): Reporting idle of ActivityRecord{4a2ccbe0 token=android.os.BinderProxy@4a2cc658 {com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity}} finished=false
 I/WindowManager(15444): Delivering pointer 0 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
 I/WindowManager(15444): Delivering pointer 1 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
 I/WindowManager(15444): Dispatching key to Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
 I/WindowManager(15444): Dispatching key to Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
 I/WindowManager(15444): Delivering pointer 0 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
 I/WindowManager(15444): Delivering pointer 1 > Window{4a5e2508 com.BoxscapeInc.SongLyrics/com.BoxscapeInc.SongLyrics.MainActivity paused=false}
 E/AndroidRuntime(28108):   at com.BoxscapeInc.SongLyrics.MainActivity.searchResult(MainActivity.java:92)
 E/AndroidRuntime(28108):   at com.BoxscapeInc.SongLyrics.MainActivity$100000000.run(MainActivity.java:82)
 W/ActivityManager(15444):   Force finishing activity com.BoxscapeInc.SongLyrics/.MainActivity
 I/ActivityManager(15444): Process com.BoxscapeInc.SongLyrics (pid 28108) has died.

有人请帮我解决这个错误。任何帮助或建议将不胜感激。

4

2 回答 2

2

在 Android 中,您只能从主线程修改 UI 组件。您正在访问searchResult从其他线程调用的方法中的组件。

你可以这样做:

et1.post(new Runnable() {
    @Override
    public void run() {
        searchResult(...);
    }
});

它将强制您将一些变量设为最终变量,因此您可以在匿名对象中使用它们。没关系。见post方法。

我个人建议您使用AsyncTask类而不是原始 Java 线程。它包括在后台线程中运行一个方法和在主线程中运行另一种方法。

于 2013-08-21T20:27:24.233 回答
0

我建议你使用这个库,而不是像你所做的那样进行网络调用

你可以看看这里

http://loopj.com/android-async-http/

您的代码将变得非常少,而不是声明可能 asynctask 单独编写大量代码,您只需使用 4 行代码

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
@Override
public void onSuccess(String response) {
    System.out.println(response);
   }
});

在 2 秒内快速获得响应非常有效。您不需要使用缓冲区阅读器或其他东西来格式化响应。您可以直接使用 onSucces 方法的字符串“response”中收到的响应。

我希望这会帮助你。:)

于 2013-08-21T20:24:52.927 回答