因此我尝试使用JSON传达的服务器提供的信息更新列表。
这是进行沟通的班级:
package com.example.simon_000.buddy;
public class TCPConnection {
private RunOnThread thread;
private Receive receive;
private MainActivity ma;
private Socket socket;
private DataInputStream input;
private DataOutputStream output;
private InetAddress address;
private int connectionPort;
private String ip;
private Exception exception;
public static String id;
public static ArrayList<members> memberList = new ArrayList<members>();
public static ArrayList<String> groupsList = new ArrayList<String>();
public static ArrayList<String> namesList = new ArrayList<String>();
public TCPConnection(String ip, int connectionPort, MainActivity ma) {
this.ip = ip;
this.connectionPort = connectionPort;
thread = new RunOnThread();
this.ma = ma;
}
public void connect() {
thread.start();
thread.execute(new Connect());
}
public void disconnect() {
thread.execute(new Disconnect());
}
public void send(String expression) {
thread.execute(new Send(expression));
}
private class Receive extends Thread {
public void run() {
String result;
try {
while (receive != null) {
result = (String) input.readUTF();
newMessage(result);
}
} catch (Exception e) { // IOException, ClassNotFoundException
receive = null;
}
}
}
public void newMessage(final String answer) {
ma.runOnUiThread(new Runnable() {
public void run() {
String message = answer;
String type;
JSONObject jObj = null;
try {
Log.d("TEST", message);
jObj = new JSONObject(message);
type = jObj.getString("type");
if (type.equals("groups")) {
recevieGroups(jObj);
}
else if (type.equals("register")) {
recevieID(jObj);
}
else if (type.equals("members")) {
receiveMembers(jObj);
}
else if (type.equals("location")) {
receiveLocations(jObj);
} else if (type.equals("locations")) {
receiveLocations(jObj);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
public void receiveLocations(JSONObject jObj) throws JSONException {
// { ”type”:”locations”, ”group”:”NAME”, ”locations”:[ {”member”:”NAME”, ”longitude”:”LONGITUDE”, ”latitude”:”LATITUDE” }, … ] }
JSONArray jArray = jObj.getJSONArray("locations");
for (int i = 0; i < jArray.length(); i++) {
members m = new members();
JSONObject jRealObject = jArray.getJSONObject(i);
m.setName(jRealObject.getString("member"));
m.setLongitude(Double.parseDouble(jRealObject.getString("longitude")));
m.setLatitude(Double.parseDouble(jRealObject.getString("latitude")));
memberList.add(m);
Log.d("TEST", " memberNAMES : " + m.getName()+" lng: "+ m.getLongitude()+" lat: "+m.getLatitude());
}
ma.updateMapMarkers(memberList);
}
public void receiveMembers(JSONObject jObj) throws JSONException {
// { “type”:”members”, “group”:”NAME”, “members”:[ {“member”:”NAME”},…] }
JSONArray jArray = jObj.getJSONArray("members");
for (int i = 0; i < jArray.length(); i++) {
String n;
JSONObject jRealObject = jArray.getJSONObject(i);
n = jRealObject.getString("member");
Log.d("TEST", " MembernamesBEFORE_ADD : " + n );
namesList.add(n);
Log.d("TEST", " memberNAMES : " + n);
}
}
public void recevieID(JSONObject jObj) throws JSONException {
id = (jObj.getString("id"));
Log.d("TEST", " ID : " + id);
}
public void recevieGroups(JSONObject jObj) throws JSONException {
JSONArray jArray = jObj.getJSONArray("groups");
for (int i = 0; i < jArray.length(); i++) {
String g;
JSONObject jRealObject = jArray.getJSONObject(i);
g = (jRealObject.getString("group"));
groupsList.add(g);
Log.d("TEST", " groupNames : " + g);
}
}
public Exception getException() {
Exception result = exception;
exception = null;
return result;
}
private class Connect implements Runnable {
public void run() {
try {
Log.d("TCPConnection", "Connect-run");
address = InetAddress.getByName(ip);
Log.d("TCPConnection-Connect", "Skapar socket");
socket = new Socket(address, connectionPort);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
output.flush();
Log.d("TCPConnection-Connect", "Strömmar klara");
newMessage("CONNECTED");
receive = new Receive();
receive.start();
} catch (Exception e) { // SocketException, UnknownHostException
Log.d("TCPConnection-Connect", e.toString());
exception = e;
newMessage("EXCEPTION");
}
}
}
public class Disconnect implements Runnable {
public void run() {
try {
if (socket != null)
socket.close();
if (input != null)
input.close();
if (output != null)
output.close();
thread.stop();
newMessage("CLOSED");
} catch (IOException e) {
exception = e;
newMessage("EXCEPTION");
}
}
}
public class Send implements Runnable {
private String exp;
public Send(String exp) {
this.exp = exp;
}
public void run() {
try {
output.writeUTF(exp);
output.flush();
} catch (IOException e) {
exception = e;
newMessage("EXCEPTION");
}
}
}
}
这是“控制器”:
package com.example.simon_000.buddy;
public class MainActivity extends Activity
implements NavigationDrawerFragment.NavigationDrawerCallbacks {
/**
* Fragment managing the behaviors, interactions and presentation of the navigation drawer.
*/
private NavigationDrawerFragment mNavigationDrawerFragment;
/**
* Used to store the last screen title. For use in {@link #restoreActionBar()}.
*/
private CharSequence mTitle;
private myMap tempMapfragment = new myMap();
private Menu menu;
private String inetAddress = "195.178.232.7";
private Integer port = 7117;
private TCPConnection connect;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
startNavDrawer();
connect = new TCPConnection(inetAddress, port, this);
connect.connect();
}
public void myPosition(String id, double LONGITUDE, double LATITUDE) {
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
try {
writer.beginObject().name("type").value("location").name("id").value(id).name("longitude").value(LONGITUDE).name("latitude").value(LATITUDE).endObject();
} catch (IOException e) {
e.printStackTrace();
}
connect.send(stringWriter.toString());
}
public void getMembers(String group) {
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
try {
writer.beginObject().name("type").value("members").name("group").value(group).endObject();
} catch (IOException e) {
e.printStackTrace();
}
connect.send(stringWriter.toString());
}
public void getGroups() {
// Aktuella grupper
// { ”type”:”groups” }
// { “type”:”groups”, ”groups”:[ {”group”:”NAME”}, …] }
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
try {
writer.beginObject().name("type").value("groups").endObject();
} catch (IOException e) {
e.printStackTrace();
}
connect.send(stringWriter.toString());
}
public void registerGroup(String groupName, String userName) {
StringWriter stringWriter = new StringWriter();
JsonWriter writer = new JsonWriter(stringWriter);
try {
writer.beginObject().name("type").value("register").name("group").value(groupName).name("member").value(userName).endObject();
} catch (IOException e) {
e.printStackTrace();
}
connect.send(stringWriter.toString());
}
public void updateMapMarkers(ArrayList<members> memberList) {
for(members m: memberList){
tempMapfragment.addMarker(m);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
connect.disconnect();
}
private void startNavDrawer() {
mNavigationDrawerFragment = (NavigationDrawerFragment)
getFragmentManager().findFragmentById(R.id.navigation_drawer);
mTitle = getTitle();
// Set up the drawer.
mNavigationDrawerFragment.setUp(
R.id.navigation_drawer,
(DrawerLayout) findViewById(R.id.drawer_layout));
}
@Override
public void onNavigationDrawerItemSelected(int position) {
// update the main content by replacing fragments
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
communication fragment2 = new communication();
switch (position) {
case 0:
// fragment1
// use fragment transaction and add the fragment to the container
fragmentTransaction.replace(R.id.container, fragment2);
fragmentTransaction.commit();
break;
case 1:
// fragment2
fragmentTransaction.replace(R.id.container, tempMapfragment);
fragmentTransaction.commit();
break;
case 2:
// fragment2
break;
default:
// fragment1
// use fragment transaction and add the fragment to the container
fragmentTransaction.replace(R.id.container, fragment2);
fragmentTransaction.commit();
}
}
public void onSectionAttached(int number) {
switch (number) {
case 1:
mTitle = getString(R.string.title_section1);
break;
case 2:
mTitle = getString(R.string.title_section2);
break;
case 3:
mTitle = getString(R.string.title_section3);
break;
}
}
public void restoreActionBar() {
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
actionBar.setDisplayShowTitleEnabled(true);
actionBar.setTitle(mTitle);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
this.menu = menu;
if (!mNavigationDrawerFragment.isDrawerOpen()) {
// Only show items in the action bar relevant to this screen
// if the drawer is not showing. Otherwise, let the drawer
// decide what to show in the action bar.
getMenuInflater().inflate(R.menu.main, menu);
restoreActionBar();
return true;
}
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//Setting maptype
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
/**
* The fragment argument representing the section number for this
* fragment.
*/
private static final String ARG_SECTION_NUMBER = "section_number";
/**
* Returns a new instance of this fragment for the given section
* number.
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
((MainActivity) activity).onSectionAttached(
getArguments().getInt(ARG_SECTION_NUMBER));
}
}
}
这是片段,它在我打开Dialog onclick的部分。
package com.example.simon_000.buddy.Fragments;
public class communication extends Fragment {
private ListView list;
private EditText groupet;
private EditText nameet;
private ListView memberList;
private Button btsend, btUpdate;
private GroupAdapter Groupadapter;
private NameAdapter Nameadapter;
public communication() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_communication, container, false);
getGroupInfo();
initiateVariables(view);
return view;
}
private void initiateVariables(View view) {
list = (ListView) view.findViewById(R.id.grouplistView);
// groupsList = new ArrayList<String>();
// namesList = new ArrayList<String>();
groupet = (EditText) view.findViewById(R.id.etgroupName);
nameet = (EditText) view.findViewById(R.id.etUsername);
btsend = (Button) view.findViewById(R.id.btSend);
btUpdate = (Button) view.findViewById(R.id.btUpdate);
groupet.setText("MadKim");
Groupadapter = new GroupAdapter(getActivity(), R.layout.row, TCPConnection.groupsList);
list.setAdapter(Groupadapter);
list.setOnItemClickListener(new listListener());
btsend.setOnClickListener(new Listener());
btUpdate.setOnClickListener(new ListenerUpdate());
}
public void getGroupInfo(){
((MainActivity)getActivity()).getGroups();
}
private class Listener implements View.OnClickListener {
@Override
public void onClick(View view) {
// sc.startThreadCommunication();
String group = groupet.getText().toString();
String name = nameet.getText().toString();
// sending query to server
if(group.isEmpty() || name.isEmpty() ){
Toast.makeText(getActivity(), "You need to fill in all the fields.", Toast.LENGTH_LONG).show();
}else {
((MainActivity)getActivity()).registerGroup(groupet.getText().toString(), nameet.getText().toString());
getGroupInfo();
Groupadapter.notifyDataSetChanged();
//hides keyboard
nameet.clearFocus();
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(
Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(nameet.getWindowToken(), 0);
//show user info
Toast.makeText(getActivity(), "Successfully registered to: "+groupet.getText().toString()+
" with username: "+nameet.getText().toString(), Toast.LENGTH_LONG).show();
groupet.setText("");
nameet.setText("");
}
}
}
private class ListenerUpdate implements View.OnClickListener {
@Override
public void onClick(View view) {
getGroupInfo();
Groupadapter = new GroupAdapter(getActivity(), R.layout.row, TCPConnection.groupsList);
list.setAdapter(Groupadapter);
Groupadapter.notifyDataSetChanged();
}
}
//REVENUES list onClick LISTENER
private class listListener implements AdapterView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) {
// ListView Clicked item index
int itemPosition = position;
Nameadapter.notifyDataSetChanged();
((MainActivity)getActivity()).getMembers(TCPConnection.groupsList.get(itemPosition).toString());
Nameadapter.notifyDataSetChanged();
//open selected finanse and show more information
Dialog d = new Dialog(getActivity());
String title = getResources().getString(R.string.dialogTitle);
d.setTitle(title);
d.setCanceledOnTouchOutside(true);
//inserting xml file in Dialog
LayoutInflater factory = LayoutInflater.from(getActivity());
View infoLayout = factory.inflate(R.layout.dialog, null);
memberList = (ListView) infoLayout.findViewById(R.id.memberList);
Button updatebt = (Button) infoLayout.findViewById(R.id.updateDialogBt);
updatebt.setOnClickListener(new updateDialogListener());
d.setContentView(infoLayout);
Nameadapter = new NameAdapter(getActivity(), R.layout.rownames, TCPConnection.namesList);
memberList.setAdapter(Nameadapter);
Nameadapter.notifyDataSetChanged();
d.show();
}
private class updateDialogListener implements View.OnClickListener {
@Override
public void onClick(View view) {
Nameadapter = new NameAdapter(getActivity(), R.layout.rownames, TCPConnection.namesList);
memberList.setAdapter(Nameadapter);
Nameadapter.notifyDataSetChanged();
}
}
}
}
这是我的错误:
10-27 17:49:00.168 24903-24903/com.example.simon_000.buddy E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.example.simon_000.buddy, PID: 24903
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(2131034141, class android.widget.ListView) with Adapter(class com.example.simon_000.buddy.customs.GroupAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1555)
at android.widget.AbsListView.onTouchUp(AbsListView.java:3624)
at android.widget.AbsListView.onTouchEvent(AbsListView.java:3436)
at android.view.View.dispatchTouchEvent(View.java:7713)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2210)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2329)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1568)
at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2277)
at android.view.View.dispatchPointerEvent(View.java:7893)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3950)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3829)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3395)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3445)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3414)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3521)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3422)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3578)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3395)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3445)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3414)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3422)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3395)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5535)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5515)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5486)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5615)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:138)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:5146)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.j
答案 0 :(得分:0)
必须从UI线程调用adapter.notifyDataSetChanged()。目前它是从后台线程调用的。
所以而不是:
adapter.notifyDataSetChanged();
你应该写:
yourActivity.runOnUiThread(new Runnable(){
public void run() {
adapter.notifyDataSetChanged();
}
});
从后台线程调用方法时。 这允许ListView使用附加到已更改的适配器的数据正确更新。