[英]Android updating listview with new data
我為飛利浦色相燈創建了一個應用程序。 我從REST請求中獲取了數據,並將json響應轉換為燈光。 我將在列表視圖中顯示燈光,一旦按下,您就可以調整飽和度,亮度和色相。 但是在我將這些與PUT請求一起保存到服務器后,它可以工作了。 但是,當我再次單擊指示燈時,數據不會更新。
如何更新列表視圖,使其包含正確的設置?
提前致謝
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類:
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);
}橋梁課:
/**
* 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) {
}
}
`
首先,從服務器獲取數據后,您必須更新列表。 然后調用下面提到的方法。
notifyDataSetChanged()
在您的適配器上
您放置了太多的notifyDataSetChanged。 僅將其放在更改列表的位置。 設置適配器一次后,無需再次設置適配器,這就是為什么調用notifyDataSetChanged的原因。 我假設onLightAvailable是您在獲取數據后設置數據的方法,因此它應如下所示:
@Override
public void onLightAvailable(Light item) {
list.add(item);
//listView.setAdapter(adapter); only once in the whole app, otherwise notify
adapter.notifyDataSetChanged();
}
刪除所有其他adapter.notifyDataSetChanged(); 並且如果您已經在整個應用程序中為該列表設置了適配器,則也應該刪除此方法中的設置。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.