0

我正在创建一个依赖于应用程序从数据库中获取的数据的 android 应用程序。为了得到这个数据,我有以下类(这个类从数据库中以 JSON 格式获取数据,翻译它并返回它):

public class Json {
    public String jsonResult;

    private Activity activity;
    private String url = "http://json.example.org/json.php";
    private String db, query;

    public Json(Activity activity) {
            this.activity = activity;
        }

    public String accessWebService(String db, String query) {
        JsonReadTask task = new JsonReadTask();

        this.db = db;
        this.query = query;

        task.execute(new String[] { url });

        try {
            task.get();
        } catch (InterruptedException e) {
            Toast.makeText(activity.getApplicationContext(), "FATAL ERROR: The thread got interrupted",
                    Toast.LENGTH_LONG).show();
        } catch (ExecutionException e) {
            Toast.makeText(activity.getApplicationContext(), "FATAL ERROR: The thread wasn't able to execute",
                    Toast.LENGTH_LONG).show();
        }
        return jsonResult;
    }

    // Async Task to access the web
    private class JsonReadTask extends AsyncTask<String, Void, String> {

        private final ProgressDialog dialog = new ProgressDialog(activity);

        protected String doInBackground(String... params) {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(params[0]);
            try {
                // add post data
                List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
                nameValuePairs.add(new BasicNameValuePair("db", db));
                nameValuePairs.add(new BasicNameValuePair("query", query));
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                HttpResponse response = httpclient.execute(httppost);
                jsonResult = inputStreamToString(response.getEntity().getContent()).toString();
                if (jsonResult.isEmpty()) {
                    Toast.makeText(activity.getApplicationContext(),
                            "Error, connection is up but didn't receive data. That's strange...", Toast.LENGTH_LONG)
                            .show();
                    this.cancel(true);
                }

            } catch (ClientProtocolException e) {
                // Toast.makeText(activity.getApplicationContext(),
                // "Error, Client Protocol Exception in JSON task",
                // Toast.LENGTH_LONG).show();
                Log.i("Json", "Error, Client Protocol Exception in JSON task");
                this.cancel(true);
            } catch (IOException e) {
                // Toast.makeText(activity.getApplicationContext(),
                // "Error, Please check your internet connection",
                // Toast.LENGTH_LONG).show();
                Log.i("Json", "Error, Please check your internet connection");
                this.cancel(true);
            }
            return null;
        }

        private StringBuilder inputStreamToString(InputStream is) {
            String rLine = "";
            StringBuilder answer = new StringBuilder();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));

            try {
                while ((rLine = rd.readLine()) != null) {
                    answer.append(rLine);
                }
            } catch (IOException e) {
                Toast.makeText(activity.getApplicationContext(), "Error..." + e.toString(), Toast.LENGTH_LONG).show();
            }
            return answer;
        }
    }// end async task
}

我注意到我的应用程序在访问数据库时冻结。经过一番谷歌搜索,我发现是方法中的 .get()accessWebService()方法导致了这种情况。我试图像这样实现一个progressDialog(我还删除了.get()方法):

private final ProgressDialog dialog = new ProgressDialog(activity);

protected void onPreExecute() {
    super.onPreExecute();
    this.dialog.setMessage("Loading...");
    this.dialog.setCancelable(false);
    this.dialog.show();
}

protected void onPostExecute(String result) {
    if (this.dialog.isShowing()) {
        this.dialog.dismiss();
    }
}

但是对话框没有出现,我得到了NullPointerException因为该应用程序仅在有数据时才有效:

result = json.accessWebService(db, query);

(也许要提到一件重要的事情:我也在 for 循环中使用这种方法)

所以现在我的问题是:如何更改我的应用程序,以便在访问数据库时获得 ProgressDialog 而没有获得NullPointerException?我担心我必须重新构建我的整个应用程序,如果我必须这样做,我该怎么做?我希望你们能理解我的问题并解决这个问题,因为我真的需要帮助。提前致谢。

PS对不起,如果我的英语不是那么好,我不是母语人士。

4

3 回答 3

3

...我发现是 accessWebService() 方法中的 .get() 方法导致了这种情况。我试图实现一个progressDialog ...

没错。get()是一个阻塞调用,简单地添加一个ProgressDialog不会修复它。您需要删除.get(),这可能会解决您ProgressDialog不显示的问题。

AnAsyncTask必须在 main 上执行,Thread因此请确保您正在执行此操作。

您遇到的另一个问题是Toast.LENGTH_LONG).show();在 上运行UI并且您有它doInBackground()不可能发生。您需要发送result到,如果需要onPostExecute(),您可以在Toast那里显示。这也可以在onProgressUpdate().

于 2013-11-06T13:33:50.230 回答
0

由于result值为空,因此发生此空指针异常。把条件放在前面

if(result != null ) {

   // CODE FOR PARSING 
} else {

   return;
}
于 2013-11-06T13:32:36.900 回答
0

您可以在 asyncTask 启动之前开始显示进度条,并在 asyncTask 完成时完成显示。

将处理程序传递给 asyncTask 和 sendMessage onPostExecute 方法。然后在 UI 线程上处理消息并隐藏进度条

例如 UI (mainActivity) 中有处理程序字段。在那里你应该处理隐藏进度条:

public Handler refreshChannelsHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case EPGManager.ERROR_MESSAGE:
                //do some stuff
                break;
            case EPGManager.SUCCESS_MESSAGE:
                //do some stuff
                break;
        }
        super.handleMessage(msg);
    }
};

然后你可以用你的处理程序调用 asyncTask

epgManager.loadChannels(refreshChannelsHandler);

AsyncTask 在方法内部,所以它看起来像这样:

public void loadChannels(Handler handler) {
    AsyncTask task = new AsyncTask() {
        @Override
        protected Object doInBackground(Object[] params) {
            try {
                //do AsyncTask Job
            } catch (Exception e) {
                return new LoadingResult((Handler) params[0], false);
            }
            return new LoadingResult((Handler) params[0], false);
        }

        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
            LoadingResult loadingResult = ((LoadingResult)o);
            sendMessageToHandler(loadingResult.handler, loadingResult.isSuccess);              
        }
    };
    task.execute(handler);
}

这是方法:

private void sendMessageToHandler(Handler handler, boolean isSuccess) {
    handler.sendEmptyMessage(isSuccess ? SUCCESS_MESSAGE : ERROR_MESSAGE);
}

最后是内部类

private class LoadingResult {
    private Handler handler;
    private boolean isSuccess;

    public LoadingResult(Handler handler, boolean isSuccess) {

        this.handler = handler;
        this.isSuccess = isSuccess;
    }

    public Handler getHandler() {
        return handler;
    }

    public void setHandler(Handler handler) {
        this.handler = handler;
    }

    public boolean isSuccess() {
        return isSuccess;
    }

    public void setSuccess(boolean isSuccess) {
        this.isSuccess = isSuccess;
    }
}

哦,别忘了常量

public static final int SUCCESS_MESSAGE = 1;
public static final int ERROR_MESSAGE = -1;

希望能帮助到你 :)

于 2013-11-06T13:48:36.773 回答