有效且高效地使用AsyncTask更新SQLite数据库

时间:2015-08-11 15:43:47

标签: android json sqlite listview android-asynctask

SQLite数据库具有用于在表中存储纬度和经度值的字段。邮件地址是在Add活动中从用户输入的。

在为输入地址提取LatLng对象的AsyncTask中,数据库写操作是其doInBackground方法的最后一个语句。然而,与预期相反,写入发生 BEFORE 响应的JSON解析,为lat和long 最初写入NULL值。

表前端的ListView显示空的Lat和Long值,但刷新后的值为正确。焦点在JSON解析之前从Add活动反冲回来,这不是所需的行为。只有在表中填充了正确的LatLng后才能返回ListView,直到显示不确定的进度条。这 IS 一切正常, 除了

  • 进度条出现并消失得太快
  • 除了LatLong值之外,ListView返回其列表项的其他组件已正确填充。

问题是,如何强制数据库写入等待JSON解析完成?

希望对这种情况的详细解释就足够了。如果需要更多详细说明或代码,请提及。

非常感谢提前!

您的善意调查的相关伪代码:

AsyncTask扩展:

    private class Geocode extends AsyncTask<String, Void, LatLng>
{
    @Override
    protected LatLng doInBackground(String...addressToGeocode) 
    {
        int DELAY = 9000;
        URL geoCodeURL;
        String jsonResponse = null;
        String geoCodeRequestURL = Contract.HTTPS_GOOGLE_GEOCODE_PRE_ADDRESS_URL 
                                   + Uri.encode(addressToGeocode[0]); 

        // Get JSON response 
        try 
        {
            geoCodeURL = new URL(geoCodeRequestURL);
            URLConnection geoCodeURLConnection = geoCodeURL.openConnection();
            BufferedReader responseReader = new BufferedReader(new InputStreamReader (geoCodeURLConnection.getInputStream()));
            StringBuilder response = new StringBuilder();
            int cp; 
            while((cp = responseReader.read()) != -1)
            {
                response.append((char)(cp));
            }

            jsonResponse = response.toString();         
            Thread.sleep(DELAY); // Force a delay, apparently not enough...
        } 
        catch (relevantExceptions e)
        {
            Log.i(LOG_TAG, e.toString());
            e.printStackTrace();
        }
        // Parse the LatLng from the JSON response
        try 
        {
            JSONObject responseObject = new JSONObject(jsonResponse);

            double lat = ((JSONArray) responseObject
                     .get("results"))
                     .getJSONObject(0)
                     .getJSONObject("geometry")
                     .getJSONObject("location")
                     .getDouble("lat");
            double lng = ((JSONArray) responseObject
                     .get("results"))
                     .getJSONObject(0)
                     .getJSONObject("geometry")
                     .getJSONObject("location")
                     .getDouble("lng");
            addressLatLng = new LatLng(lat, lng);
            object.setLat(lat);
            objet.setLng(lng);

        } 
        catch (JSONException e) 
        {
            e.printStackTrace();
        }

        if (addressLatLng != null)
        {
            ....
        }
        else 
        {
            Toast.makeText(getApplicationContext(), "Unable to Geocode", Toast.LENGTH_SHORT).show();
        }

        // Write to the database 
        dbResult = dbHelper.commitRow(object);
        return addressLatLng;               
    }

    @Override
    protected void onPreExecute() 
    {
        setProgressBarIndeterminate(true);
        setProgressBarIndeterminateVisibility(true);
    }

    @Override
    protected void onPostExecute(LatLng addressLatLng) 
    {           
        setProgressBarIndeterminateVisibility(false);
    }
} // of getLatLong()

实例化AsyncTask的Add活动中的相关代码:

    String addressToGeocode = address + 
                              " " + 
                              city + 
                              country;
    AsyncTask<String, Void, LatLng> geocodeTask = new Geocode();
    geocodeTask.execute(addressToGeocode);

添加活动由ListView活动调用,如下所示:

    @Override
public boolean onOptionsItemSelected(MenuItem item) 
{
    int itemId = item.getItemId();
    switch (itemId)
    {
        case (R.id.action_menu_add):
        {       
            Intent addIntent = new Intent(this, AddActivity.class);
            startActivityForResult(addIntent, Contract.ADD_REQUEST_CODE);

            return true;
        }
        default: 
            return false;
    }
} // of onOptionsItemSelected()

ListView&#39; onActivityResult

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
{
    if (resultCode == RESULT_OK)
    {
        Bundle b = data.getBundleExtra(GlobeShopperContract.NEW_BUNDLE);
        MyObject d = (MyObject) b.get(Contract.NEW_BUNDLE_NAME);
            collection.add(d);              
        dViewAdapter.setNotifyOnChange(true);           
        dViewAdapter.notifyDataSetChanged();
    }
    else
        ...
}

0 个答案:

没有答案