Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在android中异步读取JSON并使用其数据?_Java_Android_Android Asynctask - Fatal编程技术网

Java 如何在android中异步读取JSON并使用其数据?

Java 如何在android中异步读取JSON并使用其数据?,java,android,android-asynctask,Java,Android,Android Asynctask,我试图从一个链接下载代码,名为JSONJSON-link:并呈现它。代码如下: public class FetchJSON extends AsyncTask<Void,Void,Void> { String data = ""; String id, name, address, lat, lng, type = ""; @Override protected Void doInBackground(Void... voids) {

我试图从一个链接下载代码,名为JSONJSON-link:并呈现它。代码如下:

public class FetchJSON extends AsyncTask<Void,Void,Void> {
    String data = "";
    String id, name, address, lat, lng, type = "";

    @Override
    protected Void doInBackground(Void... voids) {
        Log.i("", "TEST");
        try {
            URL url = new URL("https://api.myjson.com/bins/ehzqu");
            HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
            InputStream inputStream = httpURLConnection.getInputStream();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
            String line = "";
            while(line!=null){
                line = bufferedReader.readLine();
                data = data + line;
            }
            Log.i("", "TEST2");
            JSONArray JA = new JSONArray(data);
            for( int i = 0 ; i < JA.length();i++)
            {
                JSONObject JO = (JSONObject) JA.get(i);
                //Log.i("", JO.toString());

                id = (String) JO.get("id");
                name = (String) JO.get("name");
                address = (String) JO.get("address");

                lat = JO.get("lat").toString();
                lng = JO.get("lng").toString();
                Log.i("JSON Values", lat + " " + lng);  //////////////////////////
                type = (String) JO.get("type");
            }
            Log.i("", "TEST3");

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

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


        return null;
    }


    @Override
    protected void onPostExecute(Void aVoid) {

        TrackDifferentLocation.data.setText(this.data);


        super.onPostExecute(aVoid);
    }

    public void printLat()
    {
        Log.i("", lat);
    }

    public String getLat (){
        return lat;
    }
    public String getLng (){
        return lng;
    }
    public String getName (){
        return name;
    }
    public String getAddress (){
        return address;
    }
    public String getID (){
        return id;
    }
    public String getType (){
        return type;
    }
}
但是在运行这段代码时,android上的应用程序崩溃了

如果我将纬度和经度硬编码为getLat/getLng函数中设置的数字,那么代码工作得很好。请注意,我已删除此问题的导入和包名称

编辑:

公共类TrackDifferentitLocation扩展了AppCompativeActivity在MapReadyCallback上的实现{ 私有谷歌地图; LatLng mLatlng; 字符串json_字符串; 公共静态文本视图数据; LatLng LatLng=null; @凌驾 受保护的void onCreate Bundle savedInstanceState{ super.onCreatesavedInstanceState; //Toast.makeTextthis,跟踪位置…,Toast.LENGTH\u LONG.show; setContentViewR.layout.activity\u track\u其他位置; SupportMapFragment mapFragment=SupportMapFragment getSupportFragmentManager .findFragmentByIdR.id.map_片段; mapFragment.getMapAsyncthis; getSupportActionBar.setDisplayShowHomeEnabledtrue; getSupportActionBar.SetDisplayHomeAsupabledTrue; //new FetchJSON.execute;//语法无效 FetchJSON f=新的FetchJSON; } @凌驾 谷歌地图上的公共空白{ mMap=谷歌地图; Log.i,已于4月1日; 显示标记; } 私有无效显示标记{ ifmMap==null返回; ifmLatlng==null返回; mMap.addMarkernew MarkerOptions.positionmLatlng; } //部分菜单见下文 @凌驾 公共布尔onCreateOptions菜单菜单{ getMenuInflater.inflateR.menu.menu,menu; 返回super.onCreateOptions菜单; } @凌驾 公共布尔值OnOptions ItemSelectedMenuItem项{ int id=item.getItemId; 如果id==android.R.id.home{ //结束活动 这是我的终点; } 开关item.getItemId{ 案例R.id.mapTypeNone: mMap.setMapTypeGoogleMap.MAP_TYPE_NONE; 打破 案例R.id.mapTypeNormal: mMap.setMapTypeGoogleMap.MAP_TYPE_NORMAL; 打破 案例R.id.mapTypeTerrain: mMap.setMapTypeGoogleMap.MAP\u TYPE\u地形; 打破 案例R.id.mapTypeSatellite: mMap.setMapTypeGoogleMap.MAP_TYPE_卫星; 打破 案例R.id.mapTypeHybrid: mMap.setMapTypeGoogleMap.MAP_TYPE_HYBRID; 打破 违约: 打破 } 返回super.on选项ItemSelectedItem; } 类FetchJSON扩展异步任务{ 字符串JSONStr=; 字符串名称,地址,类型=; 字符串lat=; 字符串lng=; 字符串id=; //双lat,液化天然气; 内定; double latDouble=-1; 双lngDouble=-1; 受保护的LatLng doInBackgroundString…args{ //LatLng LatLng=null; 试一试{ URL=新URLhttps://api.myjson.com/bins/ehzqu; HttpURLConnection HttpURLConnection=HttpURLConnection url.openConnection; InputStream InputStream=httpURLConnection.getInputStream; BufferedReader BufferedReader=新的BufferedReadernew InputStreamReaderinputStream; 字符串行=; while line!=null{ line=bufferedReader.readLine; JSONStr=JSONStr+线路; } Log.i,TEST2; JSONObject obj=新的JSONObject JSONSTR; JSONArray数组=obj.getJSONArrayserver响应; 对于int i=0;i} FetchJSON是一个异步任务,因此当您尝试访问f.getLat时, 它还没有值,因为任务尚未完成,您需要等待FetchJSON对象完成,然后再尝试访问getLat getter

我认为你可以按照以下思路做一些事情:

将映射传递给FetchJSON对象:

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    Log.i("", "onMapReady()");
    FetchJSON f = new FetchJSON(mMap);
}
并在已知纬度和经度时在FetchJSON中设置标记:

@Override
protected Void doInBackground(Void... voids) {
    ....
    lat = JO.get("lat").toString();
    lng = JO.get("lng").toString();
    type = (String) JO.get("type");

    // Set the marker here:
    double latitude = Double.valueOf(f.getLat());
    double longitude = Double.valueOf(f.getLng());
    LatLng latlng = new LatLng(latitude,longitude);
    mMap.addMarker(new MarkerOptions().position(latlng));
    ....
}
或者更好的做法可能是在onPostExecute方法中执行,该方法在doInBackground方法之后调用:

另外,您没有正确读取JSON,您期望的是一个JSONArray,而实际上它是一个JSONObject,其中包含一个JSONArray。此示例适用于您在链接中获得的JSON:

String data = "{\"server response\":[{\"id\":\"991\",\"name\":\"GPSname\",\"address\":\"GPSaddress\",\"lat\":\"52.948616\",\"lng\":\"-1.169131\",\"type\":\"GPStype\"}]}";
Log.i("TAG", data);

String id, name, address, lat, lng, type;
try {
    JSONObject json = new JSONObject(data);
    JSONArray serverResponse = json.getJSONArray("server response");

    for (int i = 0; i < serverResponse.length(); i++) {
        JSONObject JO = (JSONObject) serverResponse.get(i);
        id = (String) JO.get("id");
        name = (String) JO.get("name");
        address = (String) JO.get("address");

        lat = JO.get("lat").toString();
        lng = JO.get("lng").toString();
        type = (String) JO.get("type");

        Log.i("TAG", String.format(
            "JSON Values: id=%s, name=%s, address=%s, lat=%s, lng=%s, type=%s", 
            id, name, address, lat, lng, type));
    }
} catch (Exception e) {
    Log.e("TAG", "exception", e);
}

FetchJSON是一个异步任务,因此当您尝试访问f.getLat时,它还没有值,因为任务尚未完成,您需要等待FetchJSON对象完成,然后再尝试访问getLat getter

我认为你可以按照以下思路做一些事情:

将映射传递给FetchJSON对象:

@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    Log.i("", "onMapReady()");
    FetchJSON f = new FetchJSON(mMap);
}
并在已知纬度和经度时在FetchJSON中设置标记:

@Override
protected Void doInBackground(Void... voids) {
    ....
    lat = JO.get("lat").toString();
    lng = JO.get("lng").toString();
    type = (String) JO.get("type");

    // Set the marker here:
    double latitude = Double.valueOf(f.getLat());
    double longitude = Double.valueOf(f.getLng());
    LatLng latlng = new LatLng(latitude,longitude);
    mMap.addMarker(new MarkerOptions().position(latlng));
    ....
}
或者更好的做法可能是在onPostExecute方法中执行,该方法在doInBackground方法之后调用:

另外,您没有正确读取JSON,您期望的是一个JSONArray,而实际上它是一个JSONObject,其中包含一个JSONArray。此示例适用于您在链接中获得的JSON:

String data = "{\"server response\":[{\"id\":\"991\",\"name\":\"GPSname\",\"address\":\"GPSaddress\",\"lat\":\"52.948616\",\"lng\":\"-1.169131\",\"type\":\"GPStype\"}]}";
Log.i("TAG", data);

String id, name, address, lat, lng, type;
try {
    JSONObject json = new JSONObject(data);
    JSONArray serverResponse = json.getJSONArray("server response");

    for (int i = 0; i < serverResponse.length(); i++) {
        JSONObject JO = (JSONObject) serverResponse.get(i);
        id = (String) JO.get("id");
        name = (String) JO.get("name");
        address = (String) JO.get("address");

        lat = JO.get("lat").toString();
        lng = JO.get("lng").toString();
        type = (String) JO.get("type");

        Log.i("TAG", String.format(
            "JSON Values: id=%s, name=%s, address=%s, lat=%s, lng=%s, type=%s", 
            id, name, address, lat, lng, type));
    }
} catch (Exception e) {
    Log.e("TAG", "exception", e);
}

链接中显示的数据不是JSONArray

{服务器 回复:[{id:991,名称:GPSname,地址:GPSaddress,lat:52.948616,lng:-1.169131,类型:GPStype}]}

它是一个带有JSONArray子对象的JSONObject

编辑

为Latlng值创建一个类变量

Latlng mLatlng

现在,在onCreate方法中添加: 装载位置

以下是新代码:

 @Override
 public void onMapReady(GoogleMap googleMap) {
     mMap = googleMap;

     displayMarker();
 }


 private void loadLocation() {
     new FetchJSON().execute();
 }


 class FetchJSON extends AsyncTask<String, Integer, LatLng> {

     @Override
     protected LatLng doInBackground(String... params) {
         LatLng latLng = null;
         try {
             URL url = new URL("https://api.myjson.com/bins/ehzqu");
             HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
             InputStream inputStream = httpURLConnection.getInputStream();
             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

             StringBuilder stringBuilder = new StringBuilder();
             String line = "";
             while ((line = bufferedReader.readLine()) != null) {
                 stringBuilder.append(line).append("\n");
             }
             bufferedReader.close();

             String json = stringBuilder.toString();

             Log.e(TAG, "Return = " + json);
             String lat= "";
             String lng= "";
             JSONObject obj = new JSONObject(json);
             JSONArray array = obj.getJSONArray("server response");
             for(int i = 0; i < array.length(); i++){
                 JSONObject o = array.getJSONObject(i);

                 lat = o.optString("lat");
                 lng = o.optString("lng");
             }

             Log.e(TAG, "Lat = " + lat);
             Log.e(TAG, "lng = " + lng);

             double latDouble = Double.parseDouble(lat);
             double lngDouble = Double.parseDouble(lng);

             latLng = new LatLng(latDouble, lngDouble);
         }
         catch (Exception ex) {
             Log.e(TAG, "doInBackground --- " + ex.getMessage());
         }
         return latLng;
     }


     @Override
     protected void onPostExecute(LatLng latLng) {
         try{
             if(latLng != null){
                 mLatLng = latLng;
                 displayMarker();
             }

         }
         catch(Exception ex){
             Log.e(TAG, "onPostExecute" + ex.getMessage());
         }
     }

 }

 private void displayMarker(){
     if(mMap == null) return;
     if(mLatLng == null) return;

     MarkerOptions markerOption = new MarkerOptions();
     markerOption.position(mLatLng);
     mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLatLng, zoomFactor));
     mMap.addMarker(markerOption);
 }
在我的设备上显示的结果:

当你的谷歌地图准备好后,它将调用displayMarkers。如果由于FetchJSON未完成而导致mLatLng为null,则不会发生任何事情


您可以按照建议从onMapReady方法调用FetchJSON,但是为什么不在系统准备好GoogleMap时在后台线程中下载数据呢?

您在链接中显示的数据不是JSONArray

{服务器 回复:[{id:991,名称:GPSname,地址:GPSaddress,lat:52.948616,lng:-1.169131,类型:GPStype}]}

它是一个带有JSONArray子对象的JSONObject

编辑

为Latlng值创建一个类变量

Latlng mLatlng

现在,在onCreate方法中添加: 装载位置

以下是新代码:

 @Override
 public void onMapReady(GoogleMap googleMap) {
     mMap = googleMap;

     displayMarker();
 }


 private void loadLocation() {
     new FetchJSON().execute();
 }


 class FetchJSON extends AsyncTask<String, Integer, LatLng> {

     @Override
     protected LatLng doInBackground(String... params) {
         LatLng latLng = null;
         try {
             URL url = new URL("https://api.myjson.com/bins/ehzqu");
             HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
             InputStream inputStream = httpURLConnection.getInputStream();
             BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

             StringBuilder stringBuilder = new StringBuilder();
             String line = "";
             while ((line = bufferedReader.readLine()) != null) {
                 stringBuilder.append(line).append("\n");
             }
             bufferedReader.close();

             String json = stringBuilder.toString();

             Log.e(TAG, "Return = " + json);
             String lat= "";
             String lng= "";
             JSONObject obj = new JSONObject(json);
             JSONArray array = obj.getJSONArray("server response");
             for(int i = 0; i < array.length(); i++){
                 JSONObject o = array.getJSONObject(i);

                 lat = o.optString("lat");
                 lng = o.optString("lng");
             }

             Log.e(TAG, "Lat = " + lat);
             Log.e(TAG, "lng = " + lng);

             double latDouble = Double.parseDouble(lat);
             double lngDouble = Double.parseDouble(lng);

             latLng = new LatLng(latDouble, lngDouble);
         }
         catch (Exception ex) {
             Log.e(TAG, "doInBackground --- " + ex.getMessage());
         }
         return latLng;
     }


     @Override
     protected void onPostExecute(LatLng latLng) {
         try{
             if(latLng != null){
                 mLatLng = latLng;
                 displayMarker();
             }

         }
         catch(Exception ex){
             Log.e(TAG, "onPostExecute" + ex.getMessage());
         }
     }

 }

 private void displayMarker(){
     if(mMap == null) return;
     if(mLatLng == null) return;

     MarkerOptions markerOption = new MarkerOptions();
     markerOption.position(mLatLng);
     mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mLatLng, zoomFactor));
     mMap.addMarker(markerOption);
 }
在我的设备上显示的结果:

当你的谷歌地图准备好后,它将调用displayMarkers。如果由于FetchJSON未完成而导致mLatLng为null,则不会发生任何事情


您可以按照建议从onMapReady方法调用FetchJSON,但是为什么不在系统准备好GoogleMap时在后台线程中下载数据呢?

请提供stack traceFetchJSON是一个异步任务,因此当您尝试访问f.getLat时,它还没有值,因为任务尚未完成,在尝试访问getLat getter之前,您需要等待FetchJSON对象完成。我非常确定这是java,不是javascript。请您提供一个带有修复的答案,以便我可以标记它fixed@JackGiffin正确,自动更正在我发布时为我更改了它请提供堆栈traceFetchJSON是一个异步任务,因此,当您尝试访问f.getLat时,它还没有值,因为任务尚未完成,您需要等待FetchJSON对象完成,然后再尝试访问getLat getter。我非常确定这是java,而不是javascript。请您提供一个解决方案,以便我可以标记它fixed@JackGiffin对的“自动更正”在我发布Hi时为我更改了它,好吧,所以你给了我一个想法。我在对象初始化结束时创建了一个双lngdouble和latdouble。然后设置一个while循环,使其在值被填充之前不执行任何操作。这最终使地图能够正常工作而不会崩溃。现在的问题是,他们将lat和lon分别设置为0,从而将标记放置在错误的位置。我如何从JSON存储lat和lon有问题吗?下面是一个指向JSON的链接:@JamesDoh96我在JSON解析中添加了一点,以正确提取值。@JamesDoh96使用AsyncTask.onPostExecute更新了我的答案,这可能是这里的最佳做法。好的,你给了我一个主意。我在对象初始化结束时创建了一个双lngdouble和latdouble。然后设置一个while循环,使其在值被填充之前不执行任何操作。这最终使地图能够正常工作而不会崩溃。现在的问题是,他们将lat和lon分别设置为0,从而将标记放置在错误的位置。我如何从JSON存储lat和lon有问题吗?下面是指向JSON的链接:@JamesDoh96我在JSON解析中添加了一点,以正确提取值。@JamesDoh96 update
使用AsyncTask.onPostExecute(这可能是这里的最佳实践)编辑我的答案嗨,感谢您的回复-我已将代码更新为您的代码,但在运行emulator时,nexus 6会加载映射,但其位置为-1,0,-1,0。我在do inbackground中硬编码了一个latDouble=-5,它仍然显示-1.0,-1.0-所以我不认为它在运行?这并不不幸,这真的令人沮丧!我想我的问题是我的调试器。一分钟前,一切正常,logcat等等。另外,我的数据字符串通过httpconnection(打印到logcat的JSON数组)接收JSON。现在,在我的日志中没有发生任何事情,或者在我使用调试程序时没有发生任何事情。很难连接到应用程序。现在查看代码-行.execute似乎不是有效的行?另外,DisplayMarkers方法—您是否将其放在DetchJSON活动/类或TrackDifferentLocation活动/类中?但是你所做的一切都是有道理的还有,你得到了什么结果?结果本身似乎不是一个有效的变量!对于.execute问题,我使用FetchJSON f=newfetchjson启动;您好,感谢您的回复-我已经将我的代码更新为您的代码,但是在运行emulator时,Nexus6会加载映射,但它位于-1,0,-1,0。我在do inbackground中硬编码了一个latDouble=-5,它仍然显示-1.0,-1.0-所以我不认为它在运行?这并不不幸,这真的令人沮丧!我想我的问题是我的调试器。一分钟前,一切正常,logcat等等。另外,我的数据字符串通过httpconnection(打印到logcat的JSON数组)接收JSON。现在,在我的日志中没有发生任何事情,或者在我使用调试程序时没有发生任何事情。很难连接到应用程序。现在查看代码-行.execute似乎不是有效的行?另外,DisplayMarkers方法—您是否将其放在DetchJSON活动/类或TrackDifferentLocation活动/类中?但是你所做的一切都是有道理的还有,你得到了什么结果?结果本身似乎不是一个有效的变量!对于.execute问题,我使用FetchJSON f=newfetchjson启动;