应用程序被杀死时AsyncTask停止

时间:2016-11-10 03:18:39

标签: android json

我的代码运行正常,但是如果我回到主屏幕并返回代码停止在文本视图上运行则不显示任何内容。当我返回页面时,它不应该重新启动吗?它没有抛出任何错误,但是如果我消除了任务并重新初始化应用程序它又可以工作但是我必须保持该活动,因为如果我回到主页并返回它就停止。

public class IsstatusActivity extends AppCompatActivity {

    JSONParser jsonparser = new JSONParser();
    TextView latitude;
    TextView longitude;
    String lat;
    String longit;
    JSONObject jobj = null;

    private final ReentrantLock lock = new ReentrantLock();
    private final Condition tryAgain = lock.newCondition();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.isstatus);
        latitude = (TextView) findViewById(R.id.Coordinates);
        longitude = (TextView) findViewById(R.id.longitude);


        new Retrievedata().execute();
    }

    class Retrievedata extends AsyncTask<Void, String, Void> {


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

            try {

                while (!isCancelled()) {

                    jobj = jsonparser.makeHttpRequest("http://api.wheretheiss.at/v1/satellites/25544");

                    String lat = "latitude : " + jobj.getString("latitude");
                    String longit ="longitude : " + jobj.getString("longitude");

                    // this will cause onProgressUpdate to be called with lat & long
                    publishProgress(lat,longit);

                    // it's okay to sleep within the background thread
                    Thread.sleep(1500);

                }

            } catch (InterruptedException e) {
                Log.w("RetrieveData", "thread was interrupted", e);
            } catch (JSONException e) {
                Log.e("RetrieveData", "parse error", e);
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(String... values) {
            latitude.setText(values[0]);
            longitude.setText(values[1]);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

  

当我返回页面时,它不应该重启吗?

不一定。来自AsyncTask documentation

  

首次引入时,AsyncTasks在单个后台线程上串行执行。从DONUT开始,这被改为一个线程池,允许多个任务并行运行。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。

因此,默认情况下,从Honeycomb开始在Android版本上执行AsyncTask是序列化的,这意味着只有一个可以在任何给定时间执行。

查看Retrievedata,它被设置为循环直到它被取消(或者它被中断或遇到与JSON相关的异常)。但是,IsstatusActivity中的任务(例如,onDestroy()中)不会取消任务,因此禁止中断或错误将永久运行(或至少在您的应用被杀之前)。

部分原因是AsyncTask与活动生命周期无关。这意味着当它们在完成时创建它们的活动时它们不会自动停止 - 相反,它们会一直运行直到它们完成它们的任务。同样,因为Retrievedata循环直到它被取消并且这种情况永远不会发生,所以它会很高兴地阻止Retrievedata随后再次启动时创建的新IsstatusActivity实例的执行(更不用说任何其他您可能在其他活动中使用的AsyncTask个实例。)

有关更多背景信息,建议您查看:

您可以通过在完成活动时取消任务来解决问题,但正如其他海报所述,最好避免使用AsyncTask来完成此类任务。我对AsyncTask的理解是它最适合用于短期运行 - 实际上,这就是文档所说的:

  

AsyncTask旨在成为Thread和Handler的辅助类,并不构成通用的线程框架。理想情况下,AsyncTasks应该用于短操作(最多几秒钟。)如果需要保持线程长时间运行,强烈建议您使用java.util.concurrent包提供的各种API,例如Executor,ThreadPoolExecutor和FutureTask。

顺便说一句,发布的代码还有另一个问题。由于RetrievedataIsstatusActivity的内部类(而不是静态),因此它的每个实例都将保留对其创建的IsstatusActivity实例的隐式引用。这意味着即使在完成IsstatusActivity的任何给定实例之后,它仍将保留在内存中,直到在其中创建的Retrievedata实例完成并且可以进行垃圾回收。按照上面的说法,这永远不会发生,因为任务会永远运行。

这称为活动/上下文泄漏。每次启动和完成IsstatusActivity时,实例都会消耗内存,直到应用程序被终止。活动是重物,所以这绝对是值得避免的。

希望有所帮助!