简体   繁体   English

Android使用新数据更新列表视图

[英]Android updating listview with new data

Im creating an app for the Philips hue lights. 我为飞利浦色相灯创建了一个应用程序。 I got the data from a REST request and turned the json-response into lights. 我从REST请求中获取了数据,并将json响应转换为灯光。 I'll show the lights in a listview and once pressed you can adjust saturation, brightness, hue. 我将在列表视图中显示灯光,一旦按下,您就可以调整饱和度,亮度和色相。 But after i save these with a PUT request to the server it works. 但是在我将这些与PUT请求一起保存到服务器后,它可以工作了。 But when i click the light again the data isn't updated. 但是,当我再次单击指示灯时,数据不会更新。

How to update the listview so it contains the right settings? 如何更新列表视图,使其包含正确的设置?

Thanks in advance 提前致谢

BridgeTask class: BridgeTask类:

public class BridgeTask extends AsyncTask<String, Void, String> {
private Bridge bridge;
private BridgeTaskListener listener;
private LightAdapter adapter;

public BridgeTask(BridgeTaskListener listener, Bridge bridge, LightAdapter adapter) {
    this.listener = listener;
    this.bridge = bridge;
    this.adapter = adapter;
}





@Override
protected String doInBackground(String... params) {
    InputStream inputStream = null;
    BufferedReader reader = null;
    String urlString = "";
    String response;

    try {
        URL url = new URL(params[0]);
        URLConnection connection = url.openConnection();


         reader = new BufferedReader(
                new InputStreamReader(
                        connection.getInputStream()));
        response = reader.readLine().toString();
        String line;
        while ((line = reader.readLine()) != null) {
            response += line;
        }
    } catch (MalformedURLException e) {
        Log.e("TAG", e.getLocalizedMessage());
        return null;
    } catch (IOException e) {
        Log.e("TAG", e.getLocalizedMessage());
        return "Ewa";
    } catch (Exception e) {
        Log.e("TAG", e.getLocalizedMessage());
        return null;
    } finally {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                Log.e("TAG", e.getLocalizedMessage());
                return null;
            }
        }
    }

    return response;
}


}

protected void onPostExecute(String response) {

    try {
        JSONObject albums = new JSONObject(response);

        for(int idx = 1; idx < albums.length() + 1; idx++) {
            String lightId = String.valueOf(idx);
            String description = albums.getJSONObject("" + idx).getString("name");
            JSONObject state = albums.getJSONObject("" + idx).getJSONObject("state");
            int hue = state.getInt("hue");
            int sat = state.getInt("sat");
            int bri = state.getInt("bri");

            Light light = new Light(bridge, lightId, hue, sat, bri);
            light.setDescription(description);
            listener.onLightAvailable(light);


        }


    } catch (JSONException e ) {
        Log.e("TAG", e.getLocalizedMessage());
    }
}

MainActivity class : MainActivity类:

public class MainActivity extends AppCompatActivity implements BridgeTaskListener, Serializable, AdapterView.OnItemClickListener {

/**
 * Referentie naar de (singleton) Bridge.
 */
private final Bridge bridge = Bridge.getInstance();

/**
 * Referentie naar de lijst van Light-instanties in de Bridge.
 */
private ArrayList<Light> list = new ArrayList<>();

/**
 * ListView voor de lijst met lampen.
 */
private ListView listView;

/**
 * Adapter voor de ListView.
 */
private LightAdapter adapter;

/**
 * Lifecycle method onCreate()
 *
 * @param savedInstanceState
 */
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    listView = (ListView) findViewById(R.id.lightListView);
    adapter = new LightAdapter(this, getLayoutInflater(), list);
    listView.setAdapter(adapter);
    listView.setOnItemClickListener(this);
    fetchLights();

    adapter.notifyDataSetChanged();



}





/**
 * Implementatie van AdapterView.OnItemClickListener.onItemClick().
 *
 * @param parent
 * @param view
 * @param position
 * @param id
 */
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

    Intent i = new Intent(getApplicationContext(), LightDetailsActivity.class);
    i.putExtra("INDEX", position);
    Bundle args = new Bundle();
    args.putSerializable("LISTARRAY", (Serializable)list);
    i.putExtra("BUNDLE", args);
    startActivity(i);





}

@Override
public void onLightAvailable(Light item) {
    list.add(item);
    adapter.notifyDataSetChanged();


}

@Override
public void onLightError() {

}

private void fetchLights() {

    BridgeTask task = new BridgeTask(this, bridge, adapter);
    String[] urls = new String[]
            {"http://10.0.2.2/api/newdeveloper/lights"};
    task.execute(urls);

}Bridge class: }桥梁课:

/**
 * Singleton-referentie.
 */
private static Bridge INSTANCE;

/**
 * Tag t.b.v. logging.
 */
public final String TAG = this.getClass().getName();

/**
 * Basisdeel van url naar Philips Hue Bridge.
 */
private static final String BASE_URL = "http://10.0.2.2/api/newdeveloper";


/**
 * Private constructor (Singleton pattern).
 */
private Bridge() {
}

/**
 * Singleton-referentie.
 *
 * @return steeds dezelfde Bridge-instantie.
 */
public static final Bridge getInstance() {
    if (INSTANCE == null)
        INSTANCE = new Bridge();
    return INSTANCE;
}

/**
 * Retourneer een dummy lijst met lampen. In de volledige versie zouden we hier
 * de Bridge gaan ondervragen over de werkelijk aangesloten lampen (via een
 * HTTP GET op /api/lights).
 *
 * @return lijst van alle aangesloten lampen.
 */



/**
 * Overloaded methode voor schrijven van een boolean-waarde.
 *
 * @param id    lamp id
 * @param key   JSON key
 * @param value JSON boolean-waarde
 */
public void write(String id, String key, boolean value) {
    try {
        JSONObject o = new JSONObject();
        o.put(key, value);
        write(id, o);
    } catch (JSONException e) {
        Log.e(TAG, e.getMessage());
    }
}

/**
 * Overloaded methode voor schrijven van een integer-waarde.
 *
 * @param id    lamp id
 * @param key   JSON key
 * @param value JSON integer-waarde
 */
public void write(String id, String key, int value) {
    try {
        JSONObject o = new JSONObject();
        o.put(key, value);
        write(id, o);
    } catch (JSONException e) {
        Log.e(TAG, e.getMessage());
    }
}

/**
 * Overloaded methode voor schrijven van een String-waarde.
 *
 * @param id    lamp id
 * @param key   JSON key
 * @param value JSON String-waarde
 */
public void write(String id, String key, String value) {
    try {
        JSONObject o = new JSONObject();
        o.put(key, value);
        write(id, o);
    } catch (JSONException e) {
        Log.e(TAG, e.getMessage());
    }
}

/**
 * Private methode om het schrijven van de HTTP REST requests te laten gebeuren
 * door een subclass van AsyncTask.
 *
 * @param id   lamp id
 * @param data JSON data-object
 */
private void write(String id, JSONObject data) {
    try {
        URL url = new URL(BASE_URL + "/lights/" + id + "/state/");
        LightWriter w = new LightWriter(data);
        w.execute(url);
    } catch (IOException e) {
        //TODO: nette foutafhandeling
    }
}

/**
 * LightWriter is van AsyncTask afgeleid, en verzorgt de communicatie met de Bridge
 * voor één instantie van Light. Dit gebeurt op een andere thread dan de UI-thread.
 */
private class LightWriter extends AsyncTask<URL, Void, String> {

    private final JSONObject data;

    public LightWriter(JSONObject data) {
        this.data = data;
    }

    @Override
    protected String doInBackground(URL... params) {
        try {
            // Bouw de HTTP-connectie op en bereid een HTTP PUT request voor.
            HttpURLConnection c = (HttpURLConnection) params[0].openConnection();
            c.setRequestMethod("PUT");
            c.setDoOutput(true);
            c.connect();

            // Schrijf de JSON data in de request body.
            DataOutputStream d = new DataOutputStream(c.getOutputStream());
            d.writeBytes(data.toString());
            Log.d(TAG, data.toString());

            // Lees het resultaat dat de Bridge retourneert.
            BufferedReader b = new BufferedReader(new InputStreamReader(c.getInputStream()));
            String r = b.readLine();
            Log.d(TAG, r);
            d.close();
            c.disconnect();
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }

        return null;
    }

    @Override
    protected void onPostExecute(String response) {

    }

}

` `

First you have to update your list after fetching data from server. 首先,从服务器获取数据后,您必须更新列表。 and call then method mentioned below. 然后调用下面提到的方法。

notifyDataSetChanged()

on your Adapter 在您的适配器上

You put too many notifyDataSetChanged. 您放置了太多的notifyDataSetChanged。 Put it only at the spot where you change your list. 仅将其放在更改列表的位置。 After you set adapter once, you don't set it again and that's why you call notifyDataSetChanged. 设置适配器一次后,无需再次设置适配器,这就是为什么调用notifyDataSetChanged的原因。 I assume that onLightAvailable is that method where you set your data after fetching so it should look like this: 我假设onLightAvailable是您在获取数据后设置数据的方法,因此它应如下所示:

@Override
public void onLightAvailable(Light item) {
    list.add(item);

    //listView.setAdapter(adapter); only once in the whole app, otherwise notify 
    adapter.notifyDataSetChanged();
}

Remove all other adapter.notifyDataSetChanged(); 删除所有其他adapter.notifyDataSetChanged(); and if you've already set the adapter anywhere in the whole app for that list you should remove setting it in this method too. 并且如果您已经在整个应用程序中为该列表设置了适配器,则也应该删除此方法中的设置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM