简体   繁体   中英

App force closes with the use of runnable

I have to do a big task while a button click in my android app so i am using runnable to do background work. My works fine without the use of runnable but big task freezes it for a while. After the use of runnable my app is getting crashed on button click. Here is my code for button onClick function:

 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); 
}

Here is my logcat:

 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.

Somebody please help me with this error. Any help or suggestions would be appreciated.

In Android you can modify UI components only from main thread. You are accessing components in searchResult method called from other thread.

You can do it that way:

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

It will force you to make some variables final, so you can use them in anonymous object. It is OK. See post method.

Personally I would recommend you using AsyncTask class instead of raw Java thread. It composes running one method in background thread and running another method in main thread.

Instead of doing network calls like you have done , I suggest you use this library

you can have a look at here

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

your code will become very very less , instead of declaring so may asynctask seperately writing bulk of code , you can just use 4 lines of code

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

It is very efficient in getting the response very quickly in 2 secs. you don't need to use buffer reader or stuff to format the response. You can directly use the response recieved in string "response" of onSucces method.

I hope this will help you out. :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM