ArrayAdapter帮助,填充方法

时间:2016-09-10 21:03:35

标签: java android android-arrayadapter

我正在通过Head First Android开发工作,我遇到了问题。我尝试使用以下代码并使用从另一个类中的方法返回的数组填充listview,但我收到错误并且不明白为什么。如果我尝试在新的ArrayAdapter中调用该方法,它似乎只会给我错误,就像这样....

public class ListBikeStands extends ListActivity{

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ListView listStands = getListView();
    ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(
            this,
            android.R.layout.simple_list_item_1,
            BikesStands.getStandName());
    listStands.setAdapter(listAdapter);
}

它调用的类/方法如下......

public class BikeStands {

private static OkHttpClient client = new OkHttpClient();
private static final String key = "key";
private static final String contract = "contract";


public static String getJSON(String url) throws IOException {
    Request request = new Request.Builder().url(url).build();
    Response response = client.newCall(request).execute();
    return response.body().string();
}


private static String[] getStandName() {
    String json = null;

    try {
        json = getJSON("https://api.jcdecaux.com/vls/v1/stations?contract=" + contract + "&apiKey=" + key);
    } catch (IOException e) {
        e.printStackTrace();
    }

    Gson gson = new Gson();

    DBikesStation[] bikesAPI = gson.fromJson(json, DBikesStation[].class);
    String[] bikeStands = new String[bikesAPI.length];

    for (int i = 0; i < bikesAPI.length; ++i) {
        bikeStands[i] = bikesAPI[i].getName();
    }
    ;
    return bikeStands;
}

我收到以下错误...

  

java.lang.RuntimeException:无法启动活动   ComponentInfo {包...... dublinbikes.ListBikeStands}:   android.os.NetworkOnMainThreadException

我确实将ListBikeStands作为AndroidManifest.xml中的一个活动。

非常感谢任何帮助。谢谢。

3 个答案:

答案 0 :(得分:1)

您正在主线程中设置适配器。在适配器中,您正在调用方法&#34; getJSON()&#34;它做了一些网络。但是,您不能在主线程上进行联网。你需要在一个单独的线程中获取JSON - 使用Asynctask(在&#34中获取JSON; doInBackground()&#34;然后在&#34; onPostExecute()&#34;)中设置适配器<) / p>

答案 1 :(得分:1)

您对OkHTTPClient的使用并不完全正确。您已在UI线程上发出同步请求,因此您的错误。

public static String getJSON(String url) throws IOException {
    Request request = new Request.Builder().url(url).build();
    Response response = client.newCall(request).execute();
    return response.body().string();
}

为了发出异步请求,在后台尝试这样的事情。传递Callback并使用enqueue

重要提示:如果您认为在异步方法中需要return,则通常不正确。看到我将方法更改为void类型。回调是return变量的方法。

public static void getJSON(String url, Callback callback) throws IOException {
    Request request = new Request.Builder().url(url).build();
    client.newCall(request).enqueue(callback);
}

要调用它,请定义回调 - 在此处显示为变量,但也可以在方法调用中内嵌,就像View.OnClickListner将用于按钮一样。

您应该在Activity类中定义它,因为您将更新适配器。

final Callback bikeStandCallback = new Callback() {
      @Override public void onFailure(Call call, IOException e) {
        e.printStackTrace();
      }

      @Override public void onResponse(Call call, Response response) throws IOException {
        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

        String body = response.body().string();

        Gson gson = new Gson();

        DBikesStation[] bikesAPI = gson.fromJson(body, DBikesStation[].class);

        for (int i = 0; i < bikesAPI.length; ++i) {
            adapter.add(bikesAPI[i].getName());
        }
    }
};

在你需要的时候传递它。

public class ListBikeStands extends ListActivity {

     private ListView listStands;
     private ArrayAdapter<String> listAdapter;

     // TODO: Define above bikeStandCallback here

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        listStands = getListView();
        ArrayAdapter<String> listAdapter = new ArrayAdapter<String>(
                this,
                android.R.layout.simple_list_item_1);
        listStands.setAdapter(listAdapter);

        // TODO: Get url value
        BikeStands.getJSON(url, bikeStandCallback);
    }
}

而且,在我看来,这是非常灵活的,因为您可以为各种数据定义多个回调,再次使用不同的参数调用BikeStands.getJSON,然后对该请求执行任何操作。

总的来说,这有点像Retrofit所做的,除了可以为你添加Gson转换器。

答案 2 :(得分:0)

当您填充适配器但是因为您尝试在主线程上进行网络操作时,不会抛出您获得的错误。

您必须在其他线程上进行网络操作,您可以使用AsyncTask,您可以在this question

中找到有关该错误的其他信息

主线程上的网络被禁止,因为它通常是异步和资源密集型的,所以它可能会生成一个ANR(应用程序没有响应)