如果我将连接添加到远程 json(然后解析),为什么这个 activity 会挂起?

Why this activity hangs if i add connection to remote json (and then parsing)?

我创建了以下 activity,如果我向 getData() 方法添加注释,它会加载得很好。如果我删除评论然后我连接到远程 url 来获取和解析 json 数据。这似乎使 activity 的负载变慢。 如果我向 GetData() 调用添加注释,它会立即加载;如果使用 GetData(),它会在 4-5 秒内加载。这是我的 activity:

public class MyActivity extends Activity implements OnItemSelectedListener {
    Spinner method;
    EditText amount;
    EditText address;
    EditText email;
    EditText total;
    Button sendButton;
    List<String> methods;
    String selected_method;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.my_activity);

        method = (Spinner) findViewById(R.id.spinnerBuy); // Spinner element
        amount = (EditText) findViewById(R.id.editImporto);
        address = (EditText) findViewById(R.id.editAddress);
        email = (EditText) findViewById(R.id.editEmail);
        total = (EditText) findViewById(R.id.editTotale);
        sendButton = (Button) findViewById(R.id.button);

        method.setOnItemSelectedListener(this);

        methods = new ArrayList<String>();
        methods.add("Method 1");
        methods.add("Method 2");
        methods.add("Method 3");
        methods.add("Method 4");

        ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, R.layout.my_simple_spinner_item, methods);
        dataAdapter.setDropDownViewResource(R.layout.my_simple_spinner_dropdown_item);
        method.setAdapter(dataAdapter);

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

    public void getData() throws JSONException {
        int timeout = 10;
        String jsonString = null;

        BasicHttpParams basicParams = new BasicHttpParams();
        HttpConnectionParams.setConnectionTimeout(basicParams, timeout * 1000);
        HttpConnectionParams.setSoTimeout(basicParams, timeout * 1000 );
        DefaultHttpClient client = new DefaultHttpClient(basicParams);

        HttpGet request = new HttpGet("https://www.example.com/data.json");
        request.addHeader("Cache-Control", "no-cache");

        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);
            }

            jsonString = stringBuilder.toString();

        } catch (SocketTimeoutException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

可能是什么问题以及如何解决?

这是因为所有网络操作都必须在非UI线程中完成。您可以像这样使用异步 类 进行网络操作:

 private class GetDataAsync extends AsyncTask<Void, Void, Void > {
    @Override
    protected Void doInBackground(Void... voids) {
        //Get Data
      getData();

        return null;
    }

    @Override
    protected void onPostExecute(void result) {
 //anything you want to do it on UI 
    }
}

您必须 运行 使用异步 class 进行网络操作。 Async class 有一个方法,您可以重写名为 doInBackground 的方法,它不会 运行 在 UI 线程上。

private class MyAsyncTask extends AsyncTask<String, String, String>{


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

        //Here write your network request

        //to obtain result instead of returning null..return the String reply
        return reply;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);

        //This part runs after the async is ready, and yes this is back to the UI thread

       //s is the reply from the doInBackgroud returned value
    }
}

那你运行任务就这样

new MyAsyncTask().execute();

更新 - 进度条

要包含进度条,您还必须覆盖 onPreExecute 方法..它也在 ui 线程中 运行s 并且在 doInBackground 方法之前 运行s..所以在 preExecute 上显示进度条..

首先声明一个全局进度条

ProgressDialog progress;

然后是预执行方法

 @Override
    protected void onPreExecute() {
        super.onPreExecute();

        progress = ProgressDialog.show(this, "dialog title",
                "dialog message", true);
    }

并在执行后添加

progress.dismiss();

移除进度条

更新!! - 网络连接

您可以使用此方法检查网络..

public static boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

使用

if(isNetworkAvailable(context)){
   new MyAsyncTask().execute();
}else{
   //No Internet don't run task
}