简体   繁体   中英

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. 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. 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:

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 :

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. 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. I assume that onLightAvailable is that method where you set your data after fetching so it should look like this:

@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(); 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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