2014-10-27 42 views
0

所以即時通訊嘗試使用JSON通訊服務器提供的信息更新列表。試圖用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)); 
    } 
} 

} 

這是片段,其在其中i打開對話框的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

你adapter.notifyDataSetChanged()必須從UI線程調用。目前它是從後臺線程調用的。

所以不是:

adapter.notifyDataSetChanged(); 

你應該寫:

yourActivity.runOnUiThread(new Runnable(){ 
    public void run() { 
     adapter.notifyDataSetChanged(); 
    } 
}); 

當調用從後臺線程的方法。 這允許ListView正確更新連接到已更改的適配器的數據。