Динамическое обновление ListView из объекта JSON с помощью пользовательского ListViewAdapter - PullRequest
3 голосов
/ 19 ноября 2011

Как обычно, вопрос задается впервые пользователем Android.Три недели спустя, и я вырываю свои волосы, сделаю все возможное, чтобы объяснить проблему.

Во-первых, я использую Exlipse 3.7.1 и SDK r15 на сегодняшний день, потому что я подумал, что я попробую обновить, может быть, это и вызываетпроблемы, но, кажется, то же самое при использовании r13.

Вот рабочая копия моего кода:

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

Файл манифеста, использует 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%, по крайней мере, это работает, но теперь мне нужно попытаться динамически изменить содержимое списка, когда пользователь меняет счетчик.

Эмулятор использует -dns-server 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 от tон создал и поместил его в свой публичный метод, чтобы я мог вызывать его из MyOnItemSelectedListener, но у меня нет идей и я продемонстрировал свое полное непонимание java.

Пожалуйста, если вы ответите, попробуйте упрощенновозможно с вашим ответом.

Заранее спасибо.

ps извинения, если макет не такой, каким он должен быть, это мой первый пост

1 Ответ

0 голосов
/ 05 декабря 2011

Итак, я нашел решение для этого, может быть, кто-то может предложить лучшее, но вот что я сделал:

Вместо того, чтобы пытаться запустить PHP, который мне нужен, из спиннера, который я выбрал, чтобы использовать спиннерзагрузить новый Intent с соответствующим URL к PHP, который я хотел использовать, добавленный в 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);

Инаконец, изменив выбор счетчиков, чтобы отразить последний выбранный пользователем, если бы в счетчике было больше двух вариантов, я бы использовал пакет для передачи последнего выбранного индекса, но в моем примере у меня было только два варианта, поэтому я знал выбранныйИндекс был либо 0, либо 1 в зависимости от намерения, которое я хотел открыть.(Удостоверьтесь, что это прямо после метода setAdapter):

s.setSelection(1);

Надеемся на альтернативный метод, идущий вперед.Если кто-то может предложить способ использовать только одно действие, чтобы получить тот же результат, я был бы признателен.

...