0

Web サービスを使用して SQL Server からデータを取得し、それをタブレットの SQLite データベースにエクスポートするアプリケーションがあります。つまり、テーブルには約 25,000 のレコードがあります。たとえば、100 レコードに制限すると、コードは正常に機能します。しかし、すべてのデータをエクスポートすると、次のエラーが発生します。

02-13 13:36:31.734: E/AndroidRuntime(12821): FATAL EXCEPTION: AsyncTask #1
02-13 13:36:31.734: E/AndroidRuntime(12821): java.lang.RuntimeException: An error occured while executing doInBackground()
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.os.AsyncTask$3.done(AsyncTask.java:299)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:352)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.util.concurrent.FutureTask.setException(FutureTask.java:219)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.util.concurrent.FutureTask.run(FutureTask.java:239)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1080)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:573)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.lang.Thread.run(Thread.java:856)
02-13 13:36:31.734: E/AndroidRuntime(12821): Caused by: java.lang.OutOfMemoryError
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.lang.ThreadLocal$Values.initializeTable(ThreadLocal.java:244)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.lang.ThreadLocal$Values.rehash(ThreadLocal.java:325)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.lang.ThreadLocal$Values.cleanUp(ThreadLocal.java:254)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.lang.ThreadLocal$Values.getAfterMiss(ThreadLocal.java:438)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.lang.ThreadLocal.get(ThreadLocal.java:65)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteDatabase.getThreadSession(SQLiteDatabase.java:359)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteStatement.<init>(SQLiteStatement.java:31)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteDatabase.compileStatement(SQLiteDatabase.java:992)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.DatabaseUtils.longForQuery(DatabaseUtils.java:799)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteDatabase.getVersion(SQLiteDatabase.java:862)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:242)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:164)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at com.example.shvalidation.DatabaseHandler.InsertBook(DatabaseHandler.java:75)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at com.example.shvalidation.MainMenuScreen$TestThread.doInBackground(MainMenuScreen.java:79)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at com.example.shvalidation.MainMenuScreen$TestThread.doInBackground(MainMenuScreen.java:1)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at android.os.AsyncTask$2.call(AsyncTask.java:287)
02-13 13:36:31.734: E/AndroidRuntime(12821):    at java.util.concurrent.FutureTask.run(FutureTask.java:234)
02-13 13:36:31.734: E/AndroidRuntime(12821):    ... 4 more
02-13 13:36:32.804: E/WindowManager(12821): Activity com.example.shvalidation.MainMenuScreen has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{412636d8 V.E..... R......D 0,0-772,216} that was originally added here
02-13 13:36:32.804: E/WindowManager(12821): android.view.WindowLeaked: Activity com.example.shvalidation.MainMenuScreen has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{412636d8 V.E..... R......D 0,0-772,216} that was originally added here
02-13 13:36:32.804: E/WindowManager(12821):     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:354)
02-13 13:36:32.804: E/WindowManager(12821):     at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:216)
02-13 13:36:32.804: E/WindowManager(12821):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.Dialog.show(Dialog.java:281)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ProgressDialog.show(ProgressDialog.java:116)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ProgressDialog.show(ProgressDialog.java:99)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ProgressDialog.show(ProgressDialog.java:94)
02-13 13:36:32.804: E/WindowManager(12821):     at com.example.shvalidation.MainMenuScreen$TestThread.onPreExecute(MainMenuScreen.java:49)
02-13 13:36:32.804: E/WindowManager(12821):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:586)
02-13 13:36:32.804: E/WindowManager(12821):     at android.os.AsyncTask.execute(AsyncTask.java:534)
02-13 13:36:32.804: E/WindowManager(12821):     at com.example.shvalidation.MainMenuScreen.onCreate(MainMenuScreen.java:30)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.Activity.performCreate(Activity.java:5104)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ActivityThread.access$600(ActivityThread.java:141)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
02-13 13:36:32.804: E/WindowManager(12821):     at android.os.Handler.dispatchMessage(Handler.java:99)
02-13 13:36:32.804: E/WindowManager(12821):     at android.os.Looper.loop(Looper.java:137)
02-13 13:36:32.804: E/WindowManager(12821):     at android.app.ActivityThread.main(ActivityThread.java:5039)
02-13 13:36:32.804: E/WindowManager(12821):     at java.lang.reflect.Method.invokeNative(Native Method)
02-13 13:36:32.804: E/WindowManager(12821):     at java.lang.reflect.Method.invoke(Method.java:511)
02-13 13:36:32.804: E/WindowManager(12821):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
02-13 13:36:32.804: E/WindowManager(12821):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
02-13 13:36:32.804: E/WindowManager(12821):     at dalvik.system.NativeStart.main(Native Method)

とにかく、これらのレコードをエクスポートできることを誰かが知っているかどうか疑問に思っています. はい、25,000 を超えるレコードを SQLite にエクスポートするのはばかげていることは承知していますが、残念ながら、これは私が割り当てられたプロジェクトです。そういうわけで、私はそれを行う方法を見つけなければなりません。

編集: Web サービスを使用して SQLite に保存するコードを追加します。

package com.example.shvalidation;

import java.util.ArrayList;
import java.util.List;

import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;

public class MainMenuScreen extends Activity {
    //JSON Variables
    JSONParser jsonParser = new JSONParser();
    String pid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_menu_layout);
        new TestThread().execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main_menu_layout, menu);
        return true;
    }

    public void PlantToDome(View view) {
        Intent intent = new Intent(this, SelectLocationScreen.class);
        startActivity(intent);
    }

    //Código del Web Service
    public class TestThread extends AsyncTask<Void, Void, Void> {
        ProgressDialog dialog;
        protected void onPreExecute() {
            dialog = ProgressDialog.show(MainMenuScreen.this, "Loading", "Loading data, please wait..");
        }

        protected Void doInBackground(Void...args0) {
            int success;
            Book book = new Book();
            DatabaseHandler handler = new DatabaseHandler(MainMenuScreen.this);
            try {
                // Building Parameters
                List<NameValuePair> params = new ArrayList<NameValuePair>();
                params.add(new BasicNameValuePair("pid", pid));

                // getting product details by making HTTP request
                // Note that product details url will use GET request
                JSONObject json = jsonParser.makeHttpRequest(
                        "http://192.168.1.102:8080/WSBook.php", "GET", params);

                // check your log for json response

                // json success tag
                success = json.getInt("success");
                if (success == 1) {
                    // successfully received product details
                    JSONArray productObj = json.getJSONArray("record"); // JSON Array

                    // get first product object from JSON Array
//                    JSONObject product = productObj.getJSONObject(1);
                    for (int i = 0; i < productObj.length(); i++) {
                        JSONObject record = productObj.getJSONObject(i);
                        book.setAoiName(record.getString("aoi_name"));
                        book.setExptName(record.getString("expt_name"));
                        book.setEuID(record.getInt("eu_id"));
                        book.setX(record.getInt("x"));
                        book.setY(record.getInt("y"));
                        book.setZ(record.getInt("z"));
                        book.setRaplo(record.getString("raplo"));
//                      Book book = new Book(record.getString("aoi_name"), record.getString("expt_name"), record.getInt("eu_id"), 
//                              record.getInt("x"), record.getInt("y"), record.getInt("z"), record.getString("raplo"));
                        handler.InsertBook(book);
                    }
                }
            } catch (Exception e) {
                Log.e("error", e.toString());
            }
            return null;
        }

        protected void onPostExecute(Void unused) {
            dialog.dismiss();
        }
    }
}

編集 #2: 私の JSON パーサー クラス。

package com.example.shvalidation;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONParser {

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";

    // constructor
    public JSONParser() {

    }

    // function get json from url
    // by making HTTP POST or GET method
    public JSONObject makeHttpRequest(String url, String method,
            List<NameValuePair> params) {

        // Making HTTP request
        try {

            // check for request method
            if(method == "POST"){
                // request method is POST
                // defaultHttpClient
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpPost httpPost = new HttpPost(url);
                httpPost.setEntity(new UrlEncodedFormEntity(params));

                HttpResponse httpResponse = httpClient.execute(httpPost);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();

            }else if(method == "GET"){
                // request method is GET
                DefaultHttpClient httpClient = new DefaultHttpClient();
                String paramString = URLEncodedUtils.format(params, "utf-8");
                url += "?" + paramString;
                HttpGet httpGet = new HttpGet(url);

                HttpResponse httpResponse = httpClient.execute(httpGet);
                HttpEntity httpEntity = httpResponse.getEntity();
                is = httpEntity.getContent();
            }           

        } catch (UnsupportedEncodingException e) {
            Log.e("Unsupported Encoding", Log.getStackTraceString(e));
        } catch (ClientProtocolException e) {
            Log.e("Client Protocol", Log.getStackTraceString(e));
        } catch (IOException e) {
            Log.e("IO Exception", Log.getStackTraceString(e));
        }

        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
            is.close();
            json = sb.toString();
        } catch (Exception e) {
            Log.e("Buffer Error", "Error converting result " + e.toString());
        }

        // try parse the string to a JSON object
        try {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
            Log.e("JSON Parser", json);
        }

        // return JSON String
        return jObj;

    }
}
4

1 に答える 1

2

最初に25,000行すべてのデータをメモリにプルし、次にそれらをSQLiteに書き込もうとしているように見えます(コードを表示しなかったので、これは推測ですが、それは良い推測だと思います)。たとえば、一度に100行に制限する必要があります。つまり、Webサービスから100行を読み取り、それをSQLiteに書き込んでから、さらに100行を読み取るなどです。スレッドをもっと使いこなせるようになるかもしれませんが、それで正しい道を歩むことができます。

編集:コードを追加していただきありがとうございます。犯人は次の行のようです。

JSONObject json = jsonParser.makeHttpRequest(
    "http://192.168.1.102:8080/WSBook.php", "GET", params);

これにより、テーブル全体のテキストがWebサービスから読み込まれ、JSONObjectに詰め込まれます。JSONObjectは、携帯電話に処理するのに十分なメモリがありません。

私は2つの解決策を見ます:

  1. 行範囲を定義するパラメーターをhttpgetリクエストに追加できる場合は、現在のコードのほとんどを使用して、行0〜99の取得をループし、db、100〜199などに書き込むことができます。
  2. 行範囲を定義できない場合、またはデータベースが頻繁に変更されて一貫性のあるデータを提供することに依存できない場合は、httpリクエストからの応答の読み取りをチャンクに分割する必要があります。残念ながら、私はそこにあるすべてのjsonライブラリに精通しているわけではないので、どちらがそのプロセスに役立つかはわかりません。
于 2013-02-13T18:38:43.037 に答える