json - 使用自定义 ListViewAdapter 从 JSON 对象动态更新 ListView

标签 json listview dynamic custom-controls listview-adapter

像往常一样,这个问题来自 Android 的新用户。三周后,我会尽力解释这个问题。

首先,我从今天开始使用 Exlipse 3.7.1 和 SDK r15,因为我想我会尝试升级,也许这就是导致问题的原因,但在使用 r13 时似乎是一样的。

这是我的代码的工作副本:

主.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:gravity="center_horizontal"
    android:id="@+id/llMain"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"   
    android:orientation="vertical" >

    <LinearLayout
        android:background="@drawable/header"
        android:id="@+id/linearLayout1"
        android:layout_height="50dp"
        android:layout_width="fill_parent">

        <ImageButton
            android:background="@null"
            android:id="@+id/ibHome"
            android:layout_gravity="center_vertical"
            android:layout_height="wrap_content"
            android:layout_width="0dp"
            android:layout_weight=".25"        
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:src="@drawable/trophy_cup" />

        <ImageView
            android:background="#000000"
            android:id="@+id/imageView1"
            android:layout_height="match_parent"
            android:layout_width="1dp" />

        <TextView
            android:gravity="center_horizontal"
            android:id="@+id/lblHome"
            android:layout_height="50dp"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:paddingTop="14dp"
            android:text="@string/helloHome"
            android:textColor="@color/txtYellow"
            android:textSize="18dp"
            android:textStyle="bold"
            android:typeface="serif" />

        <ImageView
            android:id="@+id/imageView2"
            android:layout_height="match_parent" android:background="#000000"
            android:layout_width="1dp" />

        <ImageButton
            android:background="@null"
            android:focusable="true"
            android:id="@+id/ibQuit"
            android:layout_gravity="center_vertical"
            android:layout_height="wrap_content"
            android:layout_width="0dp"
            android:layout_weight=".25"  
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:src="@drawable/yellow_flag" />

    </LinearLayout>

<!-- Body code goes here -->        

     <LinearLayout
        android:id="@+id/linearLayout2"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_weight="1"
        android:gravity="center_horizontal" android:paddingTop="10dp">

        <TextView
            android:id="@+id/lblHeading"
            android:layout_width="wrap_content"
            android:layout_height="40dp"
            android:layout_weight="0.17"
            android:gravity="center_horizontal"
            android:isScrollContainer="true"
            android:text="Top"
            android:textColor="@color/txtYellow"
            android:textSize="22dp"
            android:textStyle="bold" android:paddingTop="7dp" android:typeface="serif"/>

        <Spinner
            android:entries="@array/strArrTop"
            android:id="@+id/spinTop"
            android:layout_width="90dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.44"
            android:focusableInTouchMode="true" 
            android:longClickable="true"/>

    </LinearLayout>


    <LinearLayout
        android:id="@+id/linearLayout3"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        android:gravity="center_horizontal"
        android:padding="25dp"
        android:orientation="vertical" >


        <ListView
            android:id="@+id/list1"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:isScrollContainer="true" />

    </LinearLayout>

<!-- End Body code goes here -->    

    <LinearLayout
        android:id="@+id/linearLayout4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal" >

        <TextView
            android:id="@+id/lblWidth"            
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />

        <ImageView           
            android:layout_height="120dp"
            android:layout_width="201dp"
            android:scaleType="fitXY"
            android:src="@drawable/ddo_logo" />

        <TextView
            android:id="@+id/lblHeight"            
            android:layout_height="wrap_content"
            android:layout_width="wrap_content" />

    </LinearLayout>

</LinearLayout>

mylist.xml(自定义列表适配器)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_weight="1"
        android:layout_height="wrap_content" android:gravity="left|center">

     <LinearLayout
        android:id="@+id/linearLayout1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal">

        <TextView 
         android:id="@+id/txt1"
            android:layout_width="182dp"
            android:layout_height="wrap_content" 
            android:layout_weight="0.21"
            android:textColor="@color/txtYellow" />

        <TextView 
            android:id="@+id/txt2"
            android:layout_width="40dp"
            android:layout_height="wrap_content" 
            android:textColor="@color/txtYellow" />

    </LinearLayout>
</LinearLayout>

list 文件,使用minSDK 8.0

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.hunta.DDOFastestTimes"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk android:minSdkVersion="8" />
    <uses-permission android:name="android.permission.INTERNET"/>
    <supports-screens 
        android:normalScreens="true"
        android:largeScreens="true" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:label="@string/app_name"
            android:name=".DDOFastestTimesActivity" >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

最后是有问题的 java 文件:

package com.hunta.DDOFastestTimes;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.net.ParseException;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;


public class DDOFastestTimesActivity extends Activity implements OnClickListener {
/** JSON variables */
String jc1, jc2 = null;
/** END JSON variables */

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        /** JSON variables */
        String result = null;
        InputStream is = null;
        StringBuilder sb = null;
        /** END JSON variables */

        ImageButton closeApp = (ImageButton) findViewById(R.id.ibQuit);
        closeApp.setOnClickListener(this);

        /** http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */
            /** Populating the spinner from that string-array */
            Spinner s = (Spinner) findViewById( R.id.spinTop );             
            ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( this, R.array.strArrTop, android.R.layout.simple_spinner_item );
            adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
            /** END Populating the spinner from that string-array */

            /** Create a reference to our spinner */        
            s.setAdapter( adapter );
            /** END Create a reference to our spinner */
        /** END http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */

        s.setOnItemSelectedListener(new MyOnItemSelectedListener());    

        /** JSON code to initiate the php */
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
          //http post
          try{
               HttpClient httpclient = new DefaultHttpClient();
               HttpPost httppost = new HttpPost("http://url-to-my-php-file/fastag.php");
           httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
           HttpResponse response = httpclient.execute(httppost);
           HttpEntity entity = response.getEntity();
           is = entity.getContent();
           }catch(Exception e){
               Log.e("log_tag", "Error in http connection"+e.toString());
              }
          //convert response to string
          try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
         sb = new StringBuilder();
         sb.append(reader.readLine() + "\n");
         String line="0";
         while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
          }
          is.close();
          result=sb.toString();
          }catch(Exception e){
                Log.e("log_tag", "Error converting result "+e.toString());
                  }
          //paring data

          JSONArray jArray;
          try{
                jArray = new JSONArray(result);
                JSONObject json_data=null;

                // Adding the JSON data to the list view
                int length = jArray.length();

                List<String> listContents1 = new ArrayList<String>(length);
                List<String> listContents2 = new ArrayList<String>(length);

                // Convert ListString Array to an ArrayList
                ArrayList<tblRecord> arrTxt = new ArrayList<tblRecord>();               

                // Changing the ListViews               
                for(int i=0;i<jArray.length();i++){
                    json_data = jArray.getJSONObject(i);
                    jc1 = json_data.getString("c1");
                    jc2 = json_data.getString("c2");

                    listContents1.add(json_data.getString("c1"));
                    listContents2.add(json_data.getString("c2"));

                    // Create an Array to pass to our custom view
                    tblRecord addRecord = new tblRecord(jc1, jc2);
                    arrTxt.add(addRecord);
                }

        ListView myListView1 = (ListView) findViewById(R.id.list1);
        myListView1.setAdapter(new UserItemAdapter(this, android.R.layout.simple_list_item_1, arrTxt));

        // END Adding the JSON data to the list view

        }
        catch(JSONException e1){
          Toast.makeText(getBaseContext(), "No Results Found" ,Toast.LENGTH_LONG).show();
            } catch (ParseException e1) {
                e1.printStackTrace();
    }
    /** END JSON code to initiate the php */

    }
    /** End Called when the activity is first created. */

    /** Using a custom List View */
    public class UserItemAdapter extends ArrayAdapter<tblRecord> {
        private ArrayList<tblRecord> arrList;

        public UserItemAdapter(Context context, int textViewResourceId, ArrayList<tblRecord> arrList) {
            super(context, textViewResourceId, arrList);
            this.arrList = arrList;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.mylist, null);
            }

            tblRecord user = arrList.get(position);
            if (user != null) {
                TextView c1 = (TextView) v.findViewById(R.id.txt1);
                TextView c2 = (TextView) v.findViewById(R.id.txt2);

                if (c1 != null) {
                    c1.setText(user.c1);
                }

                if(c2 != null) {
                    c2.setText(user.c2);
                }
            }
            return v;
        }
    }

    public class tblRecord {
        public String c1;
        public String c2;

        public tblRecord(String c1, String c2) {
            this.c1 = c1;
            this.c2 = c2;
        }
    }

    /** END Using a custom List View */

    /** Listener for the spinner, we will handle changes made to the spinner here */
    public class MyOnItemSelectedListener implements OnItemSelectedListener {

        public void onItemSelected(AdapterView<?> parent,
            View v, int position, long id) {
          Toast.makeText(parent.getContext(), "The top " +
              parent.getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
        }

        public void onNothingSelected(AdapterView<?> parent) {
          // Do nothing.
        }
    }
    /** END Listener for the spinner, we will handle changes made to the spinner here */

    @Override
    public void onClick(View v) {
        int id = v.getId();
        // Intent myIntent;
        switch (id) {
            case R.id.ibQuit:
                finish();
                break;
        }
    }
}

到目前为止一切正常,如果不是 100% 至少它可以正常工作,但现在我需要尝试在用户更改微调器时动态更改 ListView 的内容。

模拟器在其运行配置中使用 -dns-server xxx.xxx.xxx.xxx 我正在运行 3.7in WVGA

现在,经过 8 小时的尝试找到一种方法来做到这一点,这是我所能得到的,但它只是崩溃了:

package com.hunta.DDOFastestTimes;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ListActivity;
import android.content.Context;
import android.net.ParseException;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;


public class DDOFastestTimesActivity extends ListActivity implements OnClickListener {
private UserItemAdapter myAdapter;
private ArrayList<tblRecord> arrTxt = null;
private Runnable viewJSON;

/** JSON variables */
String jc1, jc2, result = null;
InputStream is = null;
StringBuilder sb = null;
/** END JSON variables */

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ImageButton closeApp = (ImageButton) findViewById(R.id.ibQuit);
        closeApp.setOnClickListener(this);

        /** http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */
            /** Populating the spinner from that string-array */
            Spinner s = (Spinner) findViewById( R.id.spinTop );             
            ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource( this, R.array.strArrTop, android.R.layout.simple_spinner_item );
            adapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item );
            /** END Populating the spinner from that string-array */

            /** Create a reference to our spinner */        
            s.setAdapter( adapter );
            /** END Create a reference to our spinner */
        /** END http://www.dcpagesapps.com/developer-resources/android/21-android-tutorial-spinners?start=1 */

        s.setOnItemSelectedListener(new MyOnItemSelectedListener());    

        arrTxt = new ArrayList<tblRecord>();
        this.myAdapter = new UserItemAdapter(this, R.layout.mylist, arrTxt);
        setListAdapter(this.myAdapter);
        viewJSON = new Runnable(){
            @Override
            public void run() {
                arrTxt = MyJSONFetch(0);
            }
        };
        Thread thread =  new Thread(null, viewJSON, "MagentoBackground");
        thread.start();     

        ListView myListView1 = (ListView) findViewById(R.id.list1);
        myListView1.setAdapter(new UserItemAdapter(this, android.R.layout.simple_list_item_1, arrTxt));         

    }
    /** End Called when the activity is first created. */

    private Runnable returnRes = new Runnable() {

        @Override
        public void run() {
            if(arrTxt != null && arrTxt.size() > 0){
                myAdapter.notifyDataSetChanged();
                for(int i=0;i<arrTxt.size();i++)
                myAdapter.add(arrTxt.get(i));
            }
            myAdapter.notifyDataSetChanged();
        }
    };       
    /** Using a custom List View */
    public class UserItemAdapter extends ArrayAdapter<tblRecord> {
        private ArrayList<tblRecord> arrTxt;

        public UserItemAdapter(Context context, int textViewResourceId, ArrayList<tblRecord> arrTxt) {
            super(context, textViewResourceId, arrTxt);
            this.arrTxt = arrTxt;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = vi.inflate(R.layout.mylist, null);
            }

            tblRecord user = arrTxt.get(position);
            if (user != null) {
                TextView c1 = (TextView) v.findViewById(R.id.txt1);
                TextView c2 = (TextView) v.findViewById(R.id.txt2);

                if (c1 != null) {
                    c1.setText(user.c1);
                }

                if(c2 != null) {
                    c2.setText(user.c2);
                }
            }
            return v;
        }
    }

    public class tblRecord {
        public String c1;
        public String c2;

        public tblRecord(String c1, String c2) {
            this.c1 = c1;
            this.c2 = c2;
        }
    }
    /** END Using a custom List View */

    /** Reload JSON Database from onclick listener */
    public ArrayList<tblRecord> MyJSONFetch(int position) 
    {
    ArrayList<tblRecord> arrTxt = new ArrayList<tblRecord>();
    String tmpUrl = null;
        /** JSON code to initiate the php */
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
          //http post
          try{
               HttpClient httpclient = new DefaultHttpClient();
               switch (position)
               {
               case 0:
                   tmpUrl = "http://smutlow.comp-degree.uhi.ac.uk/UG409713/DDOFastestTimes/fastag.php";
                   break;
               case 1:
                   tmpUrl = "http://smutlow.comp-degree.uhi.ac.uk/UG409713/DDOFastestTimes/fastas.php";
                   break;
               }
           HttpPost httppost = new HttpPost(tmpUrl);   
           httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
           HttpResponse response = httpclient.execute(httppost);
           HttpEntity entity = response.getEntity();
           is = entity.getContent();
           }catch(Exception e){
               Log.e("log_tag", "Error in http connection"+e.toString());
              }
          //convert response to string
          try{
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
         sb = new StringBuilder();
         sb.append(reader.readLine() + "\n");
         String line="0";
         while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
          }
          is.close();
          result=sb.toString();
          }catch(Exception e){
                Log.e("log_tag", "Error converting result "+e.toString());
                  }
          //paring data

          JSONArray jArray;
          try{
                jArray = new JSONArray(result);
                JSONObject json_data=null;

                // Adding the JSON data to the list view
                int length = jArray.length();

                List<String> listContents1 = new ArrayList<String>(length);
                List<String> listContents2 = new ArrayList<String>(length);        

                // Changing the ListViews               
                for(int i=0;i<jArray.length();i++){
                    json_data = jArray.getJSONObject(i);
                    jc1 = json_data.getString("c1");
                    jc2 = json_data.getString("c2");

                    listContents1.add(json_data.getString("c1"));
                    listContents2.add(json_data.getString("c2"));

                    // Create an Array to pass to our custom view
                    tblRecord addRecord = new tblRecord(jc1, jc2);
                    arrTxt.add(addRecord);
                }

        // END Adding the JSON data to the list view        
        }
        catch(JSONException e1){
          Toast.makeText(getBaseContext(), "No Results Found" ,Toast.LENGTH_LONG).show();
            } catch (ParseException e1) {
                e1.printStackTrace();           
    }
    /** END Reload JSON Database from onclick listener */
    runOnUiThread(returnRes);
    return arrTxt;

}  

    /** Listener for the spinner, we will handle changes made to the spinner here */
    public class MyOnItemSelectedListener implements OnItemSelectedListener {

        public void onItemSelected(AdapterView<?> parent,
            View v, int position, long id) {
            MyJSONFetch(position);
            Toast.makeText(parent.getContext(), "The top " + parent.getItemAtPosition(position).toString(), Toast.LENGTH_LONG).show();
            MyJSONFetch(position);
        }

        public void onNothingSelected(AdapterView<?> parent) {
          // Do nothing.
        }

    }

    /** END Listener for the spinner, we will handle changes made to the spinner here */
    @Override
    public void onClick(View v) {
        int id = v.getId();
        // Intent myIntent;
        switch (id) {
            case R.id.ibQuit:
                finish();
                break;
        }
    }
}

基本上我已经尝试将 JSON 代码从 onCreate 中分离出来,并将其放入自己的公共(public)方法中,以便我可以从 MyOnItemSelectedListener 中调用它,但我没有想法,并且已经证明我完全不了解 java。

如果您的回答尽量简单化。

提前谢谢你。

附注抱歉,如果布局不是它应该的样子,这是我的第一篇文章

最佳答案

所以我找到了一个解决方案,也许有人会提供更好的解决方案,但我是这样做的:

我没有尝试从微调器中触发我需要的 PHP,而是选择使用微调器加载一个新的 Intent,其中包含我想使用的 PHP 的相关 URL 添加到 Bundle。

if (position == 0) {
   Bundle myBundle = new Bundle();
   Intent myIntent;
   myBundle.putString("myPHP", "http://url-to-my-php-file/fastag.php");
   myIntent = new Intent(getBaseContext(), DDOFastestGuilds.class);
   myIntent.putExtras(myBundle);
   startActivity(myIntent); 
   onLowMemory();
   finish();
}

然后我添加了两个与第一个文件几乎相同的新 .java 文件,在开头添加了两行:

Bundle myBundle = getIntent().getExtras();
String tmpPHP =  myBundle.getString("myPHP");

我修改了调用 HttpPost 的行以指向我刚刚创建的变量 tmpPHP 而不是我在原始文件中使用的文字 URL:

HttpPost httppost = new HttpPost(tmpPHP);

最后更改微调器选择以反射(reflect)用户最后选择的选项,如果微调器中有两个以上的选项,我会使用 bundle 传递最后选择的索引,但在我的示例中我只有两个选项所以我知道所选索引是 0 或 1,具体取决于我想要打开的 Intent。 (确保它直接在 setAdapter 方法之后):

s.setSelection(1);

希望 future 有一种替代方法。 如果有人能提出一种只需要使用一个 Activity 就可以获得相同结果的方法,我将不胜感激。

关于json - 使用自定义 ListViewAdapter 从 JSON 对象动态更新 ListView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8195708/

相关文章:

json - 解码未命名对象的未命名 JSON 数组

javascript - API请求后在JS中访问数据?

android - 如何在android中创建垂直旋转木马?

c - 如何将变量设置为与另一个指针分配和指向的空间量相同?

mysql - SQL 多对多 JSON

python - 如何在 Google App Engine for Python 上设置 ETAGS?

android - 动态更改 ListView 中每个项目的 View

java - 获取 ListView 单元格对象以在构造时递增

c++ - 二进制 I/O 到具有二维动态数组的文件

c++ - C++ 中 new[ ]/delete [ ] 与 new/delete 之间的区别