应用程序启动时的空白/黑屏应付数据下载?

时间:2014-07-28 08:49:53

标签: android json service startup hang

我正在开发的应用程序在每次启动时从远程地址下载JSON文件,然后它解析JSON对象并将数据复制到手机上的SQLite。 此操作是应用程序在每个启动显示空白屏幕(或有时空白然后是黑屏)上挂起几秒钟的原因,事实上如果我尝试禁用这部分代码,应用程序可以快速启动,没有挂起。 那么,我怎么能做得更好呢?

以下是与文件下载,解析和写入本地SQLite db相关的代码(DataHandler类):

public class DataHandler {

    public DataHandler() {
    }

    public int storeData(Database db, int num) throws JSONException {

        HttpClient client = new DefaultHttpClient();
        HttpGet request = new HttpGet("http://www.example.com/data.json");
        request.addHeader("Cache-Control", "no-cache");
        long id = -1;

        try {
            HttpResponse response = client.execute(request);
            HttpEntity entity = response.getEntity();
            InputStreamReader in = new InputStreamReader(entity.getContent());
            BufferedReader reader = new BufferedReader(in);
            StringBuilder stringBuilder = new StringBuilder();
            String line = "";

            while ((line=reader.readLine()) != null) {
                stringBuilder.append(line);
            }

            JSONArray jsonArray = new JSONArray(stringBuilder.toString());
            SQLiteDatabase dbWrite = db.getWritableDatabase();
            ContentValues values = new ContentValues();

            if (jsonArray.length() == num && num != 0)
                return num;

            SQLiteDatabase dbread = db.getReadableDatabase();
            dbread.delete("mytable", "1", null);
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jObj = (JSONObject) jsonArray.getJSONObject(i);

                values.put("_id", jObj.optString("id").toString());
                values.put("city", jObj.optString("city").toString());
                values.put("country",jObj.optString("country").toString());
                values.put("addr", jObj.optString("addr").toString());
                values.put("title", jObj.optString("title").toString());
                values.put("lon", jObj.optString("lon").toString());
                values.put("email", jObj.optString("email").toString());
                values.put("phone", jObj.optString("phone").toString());
                values.put("web", jObj.optString("web").toString());
                values.put("lat", jObj.optString("lat").toString());
                values.put("desc", jObj.optString("desc").toString());
                values.put("icon", jObj.optString("icon").toString());
                values.put("category", jObj.optString("category").toString());

                id = dbWrite.insert("merchants", null, values);
            }
            num = jsonArray.length();

        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        if (id > 0)
            return num;
        else
            return -1;
    }   
}

2 个答案:

答案 0 :(得分:0)

您可能应该在后台下载和解析,并在此期间显示某些带有进度信息的启动画面。 为了避免恼人的启动画面,您还可以在启动时正常缓存数据并显示应用程序,并且只有在bakground更新完成后才刷新数据。

有几种方法可以在后台执行下载和解析操作:

我不能说在您的具体情况下什么是最佳解决方案,但我建议您阅读Processes and Threadsservice文档。

答案 1 :(得分:0)

她去你的异步任务类

class AsyncClass extends AsyncTask<String,Void,String>
{
    int result;
    Context context;
    ProgressDialog bar;
    AsynclassListener<String> listener;
    public AsyncClass(Context context, AsynclassListener listener) {//add more parameter as your method body has (i.e Database db, int num) . Don't forget to initialize them.
        this.context=context;
        this.listener=listener;
        bar = new ProgressDialog(context);
        bar.setIndeterminate(false);
    //make your progressBar here I have just given a simple example for above PB there are more parameters to set.
    }

    protected String doInBackground(String... Param){

    try{
      result = storeData();//call your method here

    }catch(Exception e){
        // Do something when crash

    }
    return ""+result;



}

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        bar.show();// By the time your data fetching and parsing will go on you this progress bar will be visible. 
    }

    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        bar.dismiss();//As soon as the work is complete the this method is called. 
         listener.onTaskComplete(""+result);
         /**
          * In your case you can later typecast back in integer once you recieve the result. 
          *  this listener will post the result to your main activity. 
          */

    }

}

这是您的界面

public interface AsynclassListener<T>{

    public void onTaskComplete(T result);

}

现在让您的Activity(Splash Class)实现该接口 这将实现方法:

 @Override
    public void onTaskComplete(String result) {
        // here the asynclass will post the result as 1 or -1 whatever you want. 
//After that you may proceed with your next part i.e switching to next activity or so.


    }

编辑:我忘了提及如何调用它:

 new AsyncClass(getApplicationContext(), this).execute("");// here you have to enter the database and other parameter values that will be required to run the method. Change it accordingly.

正如您在方法中看到的那样,您从网络中获取数据并解析: 还有第二种方法,您可以在单独的线程中调用网络cal,稍后可以在UIthread上进一步解析。

还阅读有关异步任务类的信息,以便了解参数和类的工作情况。