Running an Async Task Inside a timer in Android

2019-05-15 06:16发布

I am working on a basic chat-type application and at present I am running the code, given below :

class GetMsgs extends AsyncTask<String, String, String> {


        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(MsgViewActivity.this);
            pDialog.setMessage("Fetching..");
            pDialog.setIndeterminate(false);
            pDialog.setCancelable(true);
            pDialog.show();
        }

        @Override
        protected String doInBackground(String... arg0) {
            Intent intent = getIntent();
            String tmp = intent.getStringExtra("Header");
            List<NameValuePair> params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("Header", tmp));
            // getting JSON Object
            // Note that create product url accepts POST method
            json = jsonParser.makeHttpRequest(url,
                        "POST", params); 

            return null;
        }

        protected void onPostExecute(String file_url) {
            pDialog.dismiss();
            ListView listView_msg = (ListView)findViewById(R.id.MsgView);
            int j = 0;
            String Msgs[];
            try{
                msgs = json.getJSONArray("Messages");
                auths = json.getJSONArray("Authors");
                id = json.getString("ID");
                Msgs = new String[msgs.length()];
                for(int i = 0; i < msgs.length(); i++){
                    if ((msgs.getString(i) != "")&&(auths.getString(i) != "")){
                        Msgs[j++] = auths.getString(i) + " : " + msgs.getString(i);
                    }
                }
                msg_adapter = new ArrayAdapter<String>(MsgViewActivity.this,
                        android.R.layout.simple_list_item_1, Msgs);
                listView_msg.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
                listView_msg.setAdapter(msg_adapter);
            }       
            catch(JSONException e){
                e.printStackTrace();
            }
        }

    }   

as this :

new GetMsgs().execute();

When I run this at the start of the event in android and even at a button click, it works and performs perfectly. But then when I tried to run this at a given interval to refresh the message screen, the application crashes.

I've tried the approach I've found here: i) How to set a timer in android ii) Android timer? How-to?

But I keep getting an app-crash.

Is it not possible to run the code at specific intervals for some reason, or is it some implementational problem.

Some help will be appreciated.

LOGCAT:

04-06 11:45:40.396: V/Provider/Setting(5644): invalidate [system]: current 286 != cached 0
04-06 11:45:40.406: V/Provider/Setting(5644): from db cache, name = sound_effects_enabled value = 1
04-06 11:45:40.407: V/InputMethodManager(5644): focusOut: android.widget.EditText@41c27350 mServedView=android.widget.EditText@41c27350 winFocus=true
04-06 11:45:40.456: D/dalvikvm(5644): create interp thread : stack size=32KB
04-06 11:45:40.456: D/dalvikvm(5644): create new thread
04-06 11:45:40.456: D/dalvikvm(5644): new thread created
04-06 11:45:40.456: D/dalvikvm(5644): update thread list
04-06 11:45:40.456: D/dalvikvm(5644): threadid=11: interp stack at 0x52af2000
04-06 11:45:40.457: D/dalvikvm(5644): threadid=11: created from interp
04-06 11:45:40.457: D/dalvikvm(5644): start new thread
04-06 11:45:40.457: D/dalvikvm(5644): threadid=11: notify debugger
04-06 11:45:40.457: D/dalvikvm(5644): threadid=11 (AsyncTask #1): calling run()
04-06 11:45:40.529: V/InputMethodManager(5644): Starting input: view=android.widget.TabHost@41c23ab0
04-06 11:45:40.529: V/InputMethodManager(5644): Starting input: tba=android.view.inputmethod.EditorInfo@41c68d80 ic=null
04-06 11:45:40.529: V/InputMethodManager(5644): START INPUT: android.widget.TabHost@41c23ab0 ic=null tba=android.view.inputmethod.EditorInfo@41c68d80 controlFlags=#100
04-06 11:45:40.531: V/InputMethodManager(5644): Starting input: Bind result=InputBindResult{com.android.internal.view.IInputMethodSession$Stub$Proxy@41c698a0 com.touchtype.swiftkey/com.touchtype.KeyboardService #4807}
04-06 11:45:40.534: V/InputMethodManager(5644): onWindowFocus: null softInputMode=288 first=true flags=#1820002
04-06 11:45:40.534: V/InputMethodManager(5644): Not IME target window, ignoring
04-06 11:45:40.540: D/dalvikvm(5644): threadid=12: interp stack at 0x537ff000
04-06 11:45:40.542: D/libc-netbsd(5644): getaddrinfo: myphptestsite.bugs3.com get result from proxy >>
04-06 11:45:40.549: I/System.out(5644): propertyValue:true
04-06 11:45:40.550: I/System.out(5644): [socket][0] connection /93.188.160.82:80;LocalPort=45152(0)
04-06 11:45:40.551: I/System.out(5644): [CDS]connect[/93.188.160.82:80] tm:90
04-06 11:45:40.552: D/Posix(5644): [Posix_connect Debug]Process com.example.groupchat :80 
04-06 11:45:40.925: I/SurfaceTextureClient(5644): [STC::queueBuffer] (this:0x51247728) fps:11.83, dur:1014.51, max:391.89, min:15.83
04-06 11:45:41.562: I/SurfaceTextureClient(5644): [STC::queueBuffer] (this:0x52afe8e0) fps:54.92, dur:1001.41, max:60.19, min:7.67
04-06 11:45:41.912: I/System.out(5644): [socket][/100.69.10.243:45152] connected
04-06 11:45:41.913: I/System.out(5644): [CDS]rx timeout:0
04-06 11:45:41.922: I/System.out(5644): >doSendRequest
04-06 11:45:41.930: I/System.out(5644): <doSendRequest
04-06 11:45:42.573: I/SurfaceTextureClient(5644): [STC::queueBuffer] (this:0x52afe8e0) fps:56.37, dur:1011.19, max:23.49, min:12.03
04-06 11:45:43.365: D/dalvikvm(5644): GC_CONCURRENT freed 211K, 12% free 13462K/15171K, paused 2ms+2ms, total 17ms
04-06 11:45:43.372: D/OpenGLRenderer(5644): Flushing caches (mode 0)
04-06 11:45:43.439: I/SurfaceTextureClient(5644): [STC::queueBuffer] (this:0x51247728) fps:5.57, dur:2514.10, max:2279.30, min:12.11
04-06 11:45:43.455: V/InputMethodManager(5644): onWindowFocus: android.widget.ListView@41c2fd98 softInputMode=16 first=false flags=#1810100
04-06 11:45:43.456: V/InputMethodManager(5644): Starting input: view=android.widget.ListView@41c2fd98
04-06 11:45:43.456: V/InputMethodManager(5644): Starting input: tba=android.view.inputmethod.EditorInfo@41bf0db8 ic=null
04-06 11:45:43.456: V/InputMethodManager(5644): START INPUT: android.widget.ListView@41c2fd98 ic=null tba=android.view.inputmethod.EditorInfo@41bf0db8 controlFlags=#101
04-06 11:45:43.458: V/InputMethodManager(5644): Starting input: Bind result=InputBindResult{com.android.internal.view.IInputMethodSession$Stub$Proxy@41c0ada8 com.touchtype.swiftkey/com.touchtype.KeyboardService #4808}
04-06 11:45:45.101: D/VelocityTracker(5644): Couldn't open '/dev/touch' (No such file or directory)
04-06 11:45:45.101: D/VelocityTracker(5644): tpd read x fail: Bad file number
04-06 11:45:45.101: D/VelocityTracker(5644): tpd read y fail: Bad file number
04-06 11:45:45.260: I/SurfaceTextureClient(5644): [STC::queueBuffer] (this:0x51247728) fps:1.65, dur:1821.68, max:1796.98, min:9.99
04-06 11:45:46.205: V/Provider/Setting(5644): from settings cache , name = sound_effects_enabled value = 1
04-06 11:45:46.262: I/SurfaceTextureClient(5644): [STC::queueBuffer] (this:0x51247728) fps:3.00, dur:1001.27, max:782.15, min:67.85
04-06 11:45:46.464: D/AbsListView(5644): checkAbsListViewlLogProperty get invalid command
04-06 11:45:46.468: D/dalvikvm(5644): create interp thread : stack size=32KB
04-06 11:45:46.468: D/dalvikvm(5644): create new thread
04-06 11:45:46.469: D/dalvikvm(5644): new thread created
04-06 11:45:46.469: D/dalvikvm(5644): update thread list
04-06 11:45:46.469: D/dalvikvm(5644): threadid=13: interp stack at 0x51cc3000
04-06 11:45:46.469: D/dalvikvm(5644): threadid=13: created from interp
04-06 11:45:46.469: D/dalvikvm(5644): start new thread
04-06 11:45:46.470: D/dalvikvm(5644): threadid=13: notify debugger
04-06 11:45:46.470: D/dalvikvm(5644): threadid=13 (Timer-0): calling run()
04-06 11:45:46.470: D/dalvikvm(5644): threadid=13: exiting
04-06 11:45:46.471: W/dalvikvm(5644): threadid=13: thread exiting with uncaught exception (group=0x40f1e908)
04-06 11:45:46.473: E/AndroidRuntime(5644): FATAL EXCEPTION: Timer-0
04-06 11:45:46.473: E/AndroidRuntime(5644): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.os.Handler.<init>(Handler.java:121)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.app.Dialog.<init>(Dialog.java:107)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.app.AlertDialog.<init>(AlertDialog.java:114)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.app.AlertDialog.<init>(AlertDialog.java:98)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.app.ProgressDialog.<init>(ProgressDialog.java:77)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at com.example.groupchat.MsgViewActivity$GetMsgs.onPreExecute(MsgViewActivity.java:100)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at android.os.AsyncTask.execute(AsyncTask.java:534)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at com.example.groupchat.MsgViewActivity$1.run(MsgViewActivity.java:57)
04-06 11:45:46.473: E/AndroidRuntime(5644):     at java.util.Timer$TimerImpl.run(Timer.java:284)
04-06 11:45:46.482: V/InputMethodManager(5644): focusOut: android.widget.ListView@41c2fd98 mServedView=android.widget.ListView@41c2fd98 winFocus=false
04-06 11:45:46.493: V/InputMethodManager(5644): Not IME target window, ignoring
04-06 11:45:46.675: D/OpenGLRenderer(5644): Flushing caches (mode 0)
04-06 11:45:46.838: D/OpenGLRenderer(5644): Flushing caches (mode 0)
04-06 11:45:48.058: D/OpenGLRenderer(5644): Flushing caches (mode 0)
04-06 11:45:48.071: D/OpenGLRenderer(5644): Flushing caches (mode 0)
04-06 11:45:48.074: D/OpenGLRenderer(5644): Flushing caches (mode 1)

Working code :

 public void callAsynchronousTask() {
        final Handler handler = new Handler();
        Timer timer = new Timer();
        TimerTask doAsynchronousTask = new TimerTask() {       
            @Override
            public void run() {
                handler.post(new Runnable() {
                    public void run() {       
                        try {
                            GetMsgs performBackgroundTask = new GetMsgs();
                            // PerformBackgroundTask this class is the class that extends AsynchTask 
                            performBackgroundTask.execute();
                        } catch (Exception e) {
                            // TODO Auto-generated catch block
                        }
                    }
                });
            }
        };
        timer.schedule(doAsynchronousTask, 0, 1000*10); //execute in every 50000 ms
    }

3条回答
Lonely孤独者°
2楼-- · 2019-05-15 07:13

base on android API docs:

  1. AsyncTask execute(Params...) must be invoked on the UI thread.

  2. Each timer has one thread on which tasks are executed sequentially.

AsyncTask.execute can not be called on timer. maybe you have done this.

查看更多
手持菜刀,她持情操
3楼-- · 2019-05-15 07:17

What you could do to run code at certain intervals is use AlarmManager to run when needed. You can use setRepeating() to run it at the specified intervals.

This answer gives a small snippet on starting with AlarmManager and you can find many posts about it on SO.

AlarmManager Docs

Here is an answer that shows how to repeat code at specified intervals using a Handler and postDelayed()

查看更多
老娘就宠你
4楼-- · 2019-05-15 07:20

Important remove code new GetMsgs().execute();
from the Timer and start it in the onCreate method of your activity and on Destroy method of your activity stop your async task

 class GetMsgs extends AsyncTask<String, String, String> {

   boolean flag = false;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        flag = true;
  }

    @Override
    protected String doInBackground(String... arg0) {
        while(flag)
        {
            publishProgress("start");

            //Your Code what you are doing in the Do inBackground

            try 
            {
                Thread.sleep(3000);//Your Interval after which you want to refresh the screen
            }
            catch (InterruptedException e) 
            {
            }
            publishProgress("stop");

        }
        return null;
    }
    @Override
    protected void onProgressUpdate(String... values) 
    {
        super.onProgressUpdate(values);
        if(values[0].equalsIgnoreCase("start"))
        {
            //Create Your Dialog in it
            //Do here what you are doing in the onPreExecute    
        }
        else if(values[0].equalsIgnoreCase("stop"))
        {
            //Code you are doing in the onPostExecute
        }

    }
   @Override
    protected void onCancelled() {
        // TODO Auto-generated method stub
        super.onCancelled();
        flag = false;
    }
}   
查看更多
登录 后发表回答