【问题标题】:Android fails when trying to GET http request尝试获取 http 请求时 Android 失败
【发布时间】:2015-06-17 16:34:09
【问题描述】:

我正在尝试从 http 请求中获取信息,但它显示以下错误:

> 06-17 18:06:05.931  10913-10913/com.example.user.project
> E/RecyclerView﹕ No adapter attached; skipping layout 06-17
> 18:06:05.947  10913-10913/com.example.user.project E/AndroidRuntime﹕
> FATAL EXCEPTION: main
>     Process: com.example.user.project, PID: 10913
>     android.os.NetworkOnMainThreadException
>             at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1147)
>             at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
>             at java.net.InetAddress.getAllByNameImpl(InetAddress.java:252)
>             at java.net.InetAddress.getAllByName(InetAddress.java:215)
>             at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:142)
>             at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:169)
>             at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:124)
>             at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:365)
>             at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:560)
>             at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:492)
>             at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:470)
>             at com.example.user.project.helper.JSONParser.makeHttpRequest(JSONParser.java:55)
>             at com.example.user.project.itemActivity$getitem$1.run(itemActivity.java:120)
>             at android.os.Handler.handleCallback(Handler.java:739)
>             at android.os.Handler.dispatchMessage(Handler.java:95)
>             at android.os.Looper.loop(Looper.java:135)
>             at android.app.ActivityThread.main(ActivityThread.java:5254)
>             at java.lang.reflect.description.invoke(Native description)
>             at java.lang.reflect.description.invoke(description.java:372)
>             at com.android.internal.os.ZygoteInit$descriptionAndArgsCaller.run(ZygoteInit.java:903)
>             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

itemActivity.java:

public class itemActivity extends AppCompatActivity {

private static final String TAG_SUCCESS = "success";
private static final String TAG_item = "item";
private static final String TAG_item_NAME = "name";
private static final String TAG_item_description = "description";

Integer item_id;
String name;
String username;
String description;
TextView itemname;
TextView itemdescription;
ProgressDialog pDialog;
JSONParser jParser;
RecyclerView recycler;
ActionBar actionBar;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_item);

    Intent i = getIntent();
    if (i.hasExtra("item_id")) {
        Bundle bd = getIntent().getExtras();
        /*if ((!bd.getString("name").equals(null) || bd.getString("name").trim().length() > 0) && (!bd.getString("username").equals(null) || bd.getString("username").trim().length() > 0) && (!bd.getString("description").equals(null) || bd.getString("description").trim().length() > 0)) {
            name = bd.getString("name");
            username = bd.getString("username");
            description = bd.getString("description");
        }*/
        item_id = bd.getInt("item_id");
    }

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    actionBar = getSupportActionBar();
    actionBar.setTitle(R.string.app_name);

    itemname = (TextView) findViewById(R.id.itemName);
    itemdescription = (TextView) findViewById(R.id.itemdescription);

    new getitem().execute();
    /*recycler = (RecyclerView) findViewById(R.id.recycler);
    recycler.setHasFixedSize(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
    layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
    recycler.setLayoutManager(layoutManager);*/

}

/**
 * Background Async Task to Get complete item details
 */
class getitem extends AsyncTask<String, String, String> {

    /**
     * Before starting background thread Show Progress Dialog
     */
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(itemActivity.this);
        pDialog.setMessage(getResources().getString(R.string.loadingitem));
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
    }

    /**
     * Getting item details in background thread
     */
    protected String doInBackground(String... params) {

        // updating UI from Background Thread

        // Check for success tag
        int success;
        try {
            // Building Parameters
            List<NameValuePair> myParameters = new ArrayList<NameValuePair>();
            myParameters.add(new BasicNameValuePair("item_id", Integer.toString(item_id)));

            // getting item details by making HTTP request
            // Note that item details url will use GET request
            jParser = new JSONParser();
            JSONObject json = jParser.makeHttpRequest(AppConfig.URL_GET_item, "GET", myParameters);

            // check your log for json response
            Log.d("Single item Details", json.toString());

            // json success tag
            success = json.getInt(TAG_SUCCESS);
            if (success == 1) {
                // successfully received item details
                JSONArray itemObj = json.getJSONArray(TAG_item); // JSON Array

                // get first item object from JSON Array
                JSONObject item = itemObj.getJSONObject(0);

                // item with this pid found
                // Edit Text
                itemname.setText(item.getString(TAG_item_NAME));
                itemdescription.setText(item.getString(TAG_item_description));
            } else {
                // item with pid not found
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * After completing background task Dismiss the progress dialog
     * *
     */
    protected void onPostExecute(String file_url) {
        // dismiss the dialog once got all details
        pDialog.dismiss();
    }
}

/*itemname=(TextView)

findViewById(R.id.itemName);

itemdescription=(TextView)

findViewById(R.id.itemdescription);*/

//itemname.setText(name);
//itemdescription.setText(description);

activity_item.xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/navigation_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="@bool/fitsSystemWindows">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/status_bar_height"
            android:background="?colorPrimary" />

        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="@dimen/status_bar_height"
            android:background="?colorPrimaryDark" />

    </LinearLayout>

    <FrameLayout
        android:id="@+id/flma"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/status_bar_height">

        <TextView
            android:id="@+id/itemName"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|top"
            android:layout_marginTop="80dp"
            android:gravity="center"
            android:textAllCaps="true"
            android:textSize="25dp"
            android:textStyle="bold" />

        <ImageView
            android:id="@+id/itemPhoto"
            android:layout_width="fill_parent"
            android:layout_height="300dp"
            android:layout_gravity="center"
            android:background="#000"
            android:src="@drawable/header" />

        <TextView
            android:id="@+id/itemdescription"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|bottom"
            android:layout_marginBottom="50dp"
            android:layout_marginLeft="10dp"
            android:layout_marginRight="10dp"
            android:text="Large Text"
            android:textAppearance="?android:attr/textAppearanceLarge" />

    </FrameLayout>

    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="@bool/fitsSystemWindows"
        app:headerLayout="@layout/navigation_drawer_header"
        app:menu="@menu/navigation_drawer_menu"
        app:theme="@style/NavigationViewTheme" />

</android.support.v4.widget.DrawerLayout>

JSONParser.java:

public class JSONParser {

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

    // constructor
    public JSONParser() {

    }

    // función para obtener JSON desde la URL
    public JSONObject makeHttpRequest(String url, String description, List<NameValuePair> params) {

        try {

            if(description == "POST"){
                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(description == "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) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        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 {
            jObj = new JSONObject(json);
        } catch (JSONException e) {
            Log.e("JSON Parser", "Error parsing data " + e.toString());
        }

        return jObj;

    }
}

我正在尝试获取带有项目 ID 的 GET 请求的项目的所有信息。查看错误,我认为发出HTTP请求时失败是错误的,但我不确定。

有人知道为什么会失败吗?

谢谢!

编辑:

现在我收到以下错误:

06-17 20:56:52.856      418-428/? E/art﹕ Failed sending reply to debugger: Broken pipe
06-17 20:57:07.391      418-767/com.example.user.project_test E/AndroidRuntime﹕ FATAL EXCEPTION: AsyncTask #3
    Process: com.example.user.project_test, PID: 418
    java.lang.RuntimeException: An error occured while executing doInBackground()
            at android.os.AsyncTask$3.done(AsyncTask.java:304)
            at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
            at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
            at java.util.concurrent.FutureTask.run(FutureTask.java:242)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
     Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
            at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6357)
            at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:909)
            at android.view.ViewGroup.invalidateChild(ViewGroup.java:4690)
            at android.view.View.invalidateInternal(View.java:11801)
            at android.view.View.invalidate(View.java:11765)
            at android.view.View.invalidate(View.java:11749)
            at android.widget.TextView.checkForRelayout(TextView.java:6858)
            at android.widget.TextView.setText(TextView.java:4057)
            at android.widget.TextView.setText(TextView.java:3915)
            at android.widget.TextView.setText(TextView.java:3890)
            at com.example.user.project.itemActivity$getitem.doInBackground(itemActivity.java:132)
            at com.example.user.project.itemActivity$getitem.doInBackground(itemActivity.java:84)
            at android.os.AsyncTask$2.call(AsyncTask.java:292)
            at java.util.concurrent.FutureTask.run(FutureTask.java:237)
            at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
            at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
            at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
            at java.lang.Thread.run(Thread.java:818)
06-17 20:57:07.612      418-418/com.example.user.project_test E/WindowManager﹕ android.view.WindowLeaked: Activity com.example.user.project.itemActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{19feb64d V.E..... R......D 0,0-1026,348} that was originally added here
            at android.view.ViewRootImpl.<init>(ViewRootImpl.java:363)
            at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:271)
            at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:85)
            at android.app.Dialog.show(Dialog.java:298)
            at com.example.user.project.itemActivity$getitem.onPreExecute(itemActivity.java:96)
            at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:591)
            at android.os.AsyncTask.execute(AsyncTask.java:539)
            at com.example.user.project.itemActivity.onCreate(itemActivity.java:71)
            at android.app.Activity.performCreate(Activity.java:5990)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
            at android.app.ActivityThread.access$800(ActivityThread.java:151)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.description.invoke(Native description)
            at java.lang.reflect.description.invoke(description.java:372)
            at com.android.internal.os.ZygoteInit$descriptionAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

【问题讨论】:

    标签: java android json get httprequest


    【解决方案1】:

    它失败了,因为你试图在主线程 android.os.NetworkOnMainThreadException 上获取配方

    似乎有问题的是:

    JSONObject json = jParser.makeHttpRequest(AppConfig.URL_GET_RECIPE, "GET", params);

    这个调用失败的原因是你把它包装在一个runOnUIThread 调用中,它将尝试处理主线程上的所有内容。这反过来会导致您的网络请求,尽管处于异步任务中,但在主线程上运行。


    params 的问题

    protected String doInBackground(String... params) {
    
            // updating UI from Background Thread
            runOnUiThread(new Runnable() {
                public void run() {
                    // Check for success tag
                    int success;
                    try {
                        // Building Parameters
                        List<NameValuePair> params = new ArrayList<NameValuePair>();
    

    doInBackground 的参数称为 params,您正在尝试创建另一个名为 params 的变量。换个方式

    List&lt;NameValuePair&gt; params = new ArrayList&lt;NameValuePair&gt;();

    类似

    List&lt;NameValuePair&gt; myParameters = new ArrayList&lt;NameValuePair&gt;();

    确保同时更新对参数的所有引用。这最好通过 IDE 中的重构工具来完成。


    如此接近!这个错误也很容易修复。

    默认情况下,doInBackground 在由 AsyncTask 生成和维护的后台线程中运行。因为这是一个后台线程而不是执行 UI 的主线程,您不能在除主线程之外的任何其他线程上更改 UI(编辑文本、标签、按钮等)。 这是我们要使用runOnUIThread的地方。目前,在您的 doInBackground 中,您有以下几行:

    recipename.setText(recipe.getString(TAG_RECIPE_NAME));
    recipemethod.setText(recipe.getString(TAG_RECIPE_METHOD));
    

    只需将它们包裹在runOnUIThread

    runOnUIThread(new Runnable()
    {
        recipename.setText(recipe.getString(TAG_RECIPE_NAME));
        recipemethod.setText(recipe.getString(TAG_RECIPE_METHOD));
    });
    

    但是,我建议您在此方法中返回字符串并在 onPostExecute 中执行所有 UI 更改,因为此方法默认在 UI 线程上运行。您还可以在 onProgressUpdate 中进行更改,因为这将在 UI 线程上运行。

    【讨论】:

    • 谢谢!如何避免线程在主线程中处理?我只是尝试删除 runOnUIThread 但在 List params = new ArrayList();出现错误:“范围内已定义变量'params'”。什么是正确的做法?
    • @alexca 我在回答中添加了一个部分来帮助您
    • 谢谢!我想多亏了你,我几乎解决了!我已经进行了更改,现在加载了活动,但由于我在问题中添加的错误导致 APP 崩溃。谢谢!
    • @alexca 另一个问题,另一个更新!希望这会有所帮助:) 随时将其标记为答案
    • 谢谢@iismathwizard!我希望尽快解决问题,感谢您帮助我解决问题! :)
    猜你喜欢
    • 2014-12-14
    • 1970-01-01
    • 2018-02-20
    • 1970-01-01
    • 2023-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多