【问题标题】:JSON not loading into listview correctly - AndroidJSON 未正确加载到列表视图中 - Android
【发布时间】:2023-03-07 17:38:01
【问题描述】:

我从服务器收到一个 JSON 数组,如下所示,

[{"id":"3","name":"Spanish 101","uid":"54f22e5c87cbd3.52439435","did":"fba6a04d1d6375fbdbb102953e984002"},
{"id":"4","name":"Calc","uid":"54f22e5c87cbd3.52439435","did":"fb7f4ba1eae22eb396dc7cbd465a10b4"},
{"id":"5","name":"Stats 250","uid":"54f22e5c87cbd3.52439435","did":"f6adca44250056c17fec56530faee7c9"}]

我想把这些信息放到一个列表视图中

这是我的代码,假设处理此 JSON 数组并将其放入列表视图中

package com.example.library;
import java.io.BufferedReader;
import java.io.IOException;
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.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.os.AsyncTask;

public class FetchDataTask extends AsyncTask<String, Void, String>{
    private final FetchDataListener listener;
    private String msg;

    public FetchDataTask(FetchDataListener listener) {
        this.listener = listener;
    }

    @Override
    protected String doInBackground(String... params) {
        if(params == null) return null;

        // get url from params
        String url = params[0];

        try {
            // create http connection
            HttpClient client = new DefaultHttpClient();
            HttpGet httpget = new HttpGet(url);

            // connect
            HttpResponse response = client.execute(httpget);

            // get response
            HttpEntity entity = response.getEntity();

            if(entity == null) {
                msg = "No response from server";
                return null;
            }

            // get response content and convert it to json string
            InputStream is = entity.getContent();
            return streamToString(is);
        }
        catch(IOException e){
            msg = "No Network Connection";
        }

        return null;
    }

    @Override
    protected void onPostExecute(String sJson) {
        if(sJson == null) {
            if(listener != null) listener.onFetchFailure(msg);
            return;
        }

        try {
            // convert json string to json array
            JSONArray aJson = new JSONArray(sJson);
            // create apps list
            List<Application> apps = new ArrayList<Application>();

            for(int i=0; i<aJson.length(); i++) {
                JSONObject json = aJson.getJSONObject(i);
                Application app = new Application();
                app.setTitle(json.getString("name"));
                // add the app to apps list
                apps.add(app);
            }

            //notify the activity that fetch data has been complete
            if(listener != null) listener.onFetchComplete(apps);
        } catch (JSONException e) {
            msg = "Invalid response";
            if(listener != null) listener.onFetchFailure(msg);
            return;
        }
    }

    /**
     * This function will convert response stream into json string
     * @param is respons string
     * @return json string
     * @throws IOException
     */
    public String streamToString(final InputStream is) throws IOException{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;

        try {
            while ((line = reader.readLine()) != null) {
                sb.append(line + "\n");
            }
        }
        catch (IOException e) {
            throw e;
        }
        finally {
            try {
                is.close();
            }
            catch (IOException e) {
                throw e;
            }
        }

        return sb.toString();
    }
}

FetchDataListener

package com.example.library;
import java.util.List;

public interface FetchDataListener {
    public void onFetchComplete(List<Application> data);
    public void onFetchFailure(String msg);
}

我目前只尝试将name 放入列表视图中,当我运行此代码时,只会将第一个数组放入列表视图中。所以只有一个列表项,名称为 Spanish 101。

为什么其他数组名没有被放入列表视图?

应用程序适配器

package com.example.library;
import java.text.NumberFormat;
import java.util.List;

import android.content.Context;
import android.content.res.Resources;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.R;

public class ApplicationAdapter extends ArrayAdapter<Application>{
    private List<Application> items;

    public ApplicationAdapter(Context context, List<Application> items) {
        super(context, R.layout.app_custom_list, items);
        this.items = items;
    }

    @Override
    public int getCount() {
        return items.size();
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;

        if(v == null) {
            LayoutInflater li = LayoutInflater.from(getContext());
            v = li.inflate(R.layout.app_custom_list, null);
        }

        Application app = items.get(position);

        if(app != null) {
            TextView titleText = (TextView)v.findViewById(R.id.titleTxt);

            if(titleText != null) titleText.setText(app.getTitle());

        }

        return v;
    }
}

获取和设置

package com.example.library;

public class Application {
    private String title;

    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
}

具有 ListView 的 MainActivity

package com.example;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.ClipData;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.R;
import com.example.library.Application;
import com.example.library.ApplicationAdapter;
import com.example.library.DatabaseHandler;
import com.example.library.FetchDataListener;
import com.example.library.FetchDataTask;
import com.example.library.UserFunctions;

import java.util.HashMap;
import java.util.List;

public class MainActivity extends ListActivity implements FetchDataListener {

    private ProgressDialog dialog;
    ProgressDialog  nDialog;
    AlertDialog.Builder dlgAlert;
    ListView listView ;
    TextView tv;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();

        tv = (TextView) findViewById(R.id.tv);
        nDialog  = new ProgressDialog(MainActivity.this);

        //Action bar information
        android.app.ActionBar mActionBar = getActionBar();
        assert mActionBar != null;
        mActionBar.setDisplayShowHomeEnabled(false);
        mActionBar.setDisplayShowTitleEnabled(false);
        LayoutInflater mInflater = LayoutInflater.from(this);
        View mCustomView = mInflater.inflate(R.layout.custom_actionbar, null);

        //FIX THISSSSS TO LOGOUT BUTTON
        RelativeLayout settingButton = (RelativeLayout) mCustomView
                .findViewById(R.id.settingButton);
        settingButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View view) {

                UserFunctions logout = new UserFunctions();
                logout.logoutUser(getApplicationContext());
                Intent startup = new Intent(getApplicationContext(), StartUp.class);
                startup.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(startup);
                finish();
            }
        });

        mActionBar.setCustomView(mCustomView);
        mActionBar.setDisplayShowCustomEnabled(true);

        //End action bar information

    }//End onCreate

    private void initView() {
        // show progress dialog
        DatabaseHandler db = new DatabaseHandler(getApplicationContext());
        HashMap user = new HashMap();
        user = db.getUserDetails();
        String uid = user.get("unique_id").toString();
        dialog = ProgressDialog.show(this, "", "Loading...");

        String url = "www.example.com";
        FetchDataTask task = new FetchDataTask(this);
        task.execute(url);
    }

    @Override
    public void onFetchComplete(List<Application> data) {
        // dismiss the progress dialog
        if(dialog != null)  dialog.dismiss();
        // create new adapter
        ApplicationAdapter adapter = new ApplicationAdapter(this, data);
        // set the adapter to list
        setListAdapter(adapter);
    }

    @Override
    public void onFetchFailure(String msg) {
        // dismiss the progress dialog
        if(dialog != null)  dialog.dismiss();
        // show failure message
        Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
    }

}//End Activity

【问题讨论】:

  • 您能否提供一部分代码,将应用列表设置为适配器?
  • 另外,我看不到您在代码中的任何位置调用 getTitle()。您应该发布完整的代码以获得适当的帮助。
  • 所有代码已添加
  • 在此ApplicationAdapter adapter = new ApplicationAdapter(this, data); // set the adapter to list setListAdapter(adapter); 之后致电adapter.notifyDataSetChanged()。也许它会工作。
  • @ShifarShifz 我试过adapter.notifyDataSetChanged()它没有修复它。

标签: android arrays json android-listview


【解决方案1】:

这就是我处理 ListView 和 CustomAdapter 的方式

在Activity的onCreate()中

        //Photos Model List
        photoList = new ArrayList<Photos>();

        //ListView
        lvGalleryPhotos = (ListView) parentView.findViewById(R.id.lvGalleryPhotos);

        //My CustomAdapter
        pgAdapter = new PhotoGalleryAdapter(photoList, getSherlockActivity());  


        //Setting adapter to GridView
        lvGalleryPhotos.setAdapter(pgAdapter);

        //Parsing JSON
        for(int i=0;i<10;i++){

                    //each result contains details about a image
                    JSONObject result = results.getJSONObject(i);

                    //Real Parsing
                    int width = result.getInt("width");
                    int height = result.getInt("height");
                    String title = result.getString("titleNoFormatting");
                    String url = result.getString("unescapedUrl");
                    //Make it workable so replace \u003d with =
                    String tbUrl = result.getString("tbUrl").replace("\u003d", "=");

                    //Creating photo object and inserting all collected information into it.
                    Photos photo = new Photos();
                    photo.setHeight(height);
                    photo.setWidth(width);
                    photo.setTitle(title);
                    photo.setURL(url);
                    photo.setTbUrl(tbUrl);

                    //Adding each Photo Object to PhotoList
                    photoList.add(photo);

                }       

        //Informing that data has changed
        pgAdapter.notifyDataSetChanged();

我的自定义适配器

    public class PhotoGalleryAdapter extends BaseAdapter {

        ImageLoader mImageLoader;
        List<Photos> photoList;
        Context mContext;
        BlowIt blw;
        LayoutInflater mLInflater;

        public PhotoGalleryAdapter(List<Photos> photoList,Context mContext){
            this.photoList = photoList;
            this.mContext = mContext;
            blw = new BlowIt(mContext);
        }

        @Override
        public int getCount() {
            return photoList.size();
        }

        @Override
        public Object getItem(int position) {

            return photoList.get(position);
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {

            //Creating layout inflater
            if(mLInflater==null){
                mLInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            }

            //Inflating Layout
            if(convertView==null){
                convertView = mLInflater.inflate(R.layout.gallery_single_photo,parent,false);
            }

            //Getting Object
            final Photos photo = photoList.get(position);

            //Single Image
            NetworkImageView nivGalleryPhoto = (NetworkImageView) convertView.findViewById(R.id.nivGalleryPhoto);
            TextView tvPhotoName = (TextView) convertView.findViewById(R.id.tvPhotoName);
            TextView tvPhotoDesc = (TextView) convertView.findViewById(R.id.tvPhotoDesc);

            final String photoDescr = photo.getHeight()+"x"+photo.getWidth();

            nivGalleryPhoto.setImageUrl(photo.getTbUrl(), mImageLoader);
            tvPhotoName.setText(photo.getTitle());
            tvPhotoDesc.setText(photoDescr);

            convertView.setTag(photo);
            convertView.setId(position);

            //This will trigger when ever the user clicks on a specific image
            convertView.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    //This will prompt automatically context menu
                    v.showContextMenu();

                }
            });





            return convertView;
        }


    }

和布局

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

       <ListView 
           android:id="@+id/lvGalleryPhotos"
           android:layout_height="wrap_content"
           android:layout_width="match_parent"
           ></ListView>

    </LinearLayout>

还有gallery_single_photo.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:padding="10dp"
    android:layout_height="wrap_content" >
    <!-- <com.android.volley.toolbox.NetworkImageView -->
    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/nivGalleryPhoto"   
        android:layout_height="90dp"
        android:scaleType="centerCrop"
        android:layout_width="75dp"
        android:contentDescription="@string/dummy_desc"
        />

    <TextView
        android:id="@+id/tvPhotoName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textStyle="bold"
        android:layout_alignTop="@+id/nivGalleryPhoto"
        android:layout_marginLeft="5dp"
        android:layout_toRightOf="@+id/nivGalleryPhoto"
        android:text="Large Text"/>

    <TextView
        android:id="@+id/tvPhotoDesc"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/tvPhotoName"
        android:layout_below="@+id/tvPhotoName"
        android:text="Medium Text"
        android:textSize="13sp"
        android:textColor="@color/border_black" />

</RelativeLayout>

以上所有代码都可以用这样的项目制作一个listView

【讨论】:

    【解决方案2】:

    getView(...) 中使用 ViewHolder 设计模式:

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View v = convertView;
        ViewHolder holder;
    
        if(v == null) {
            LayoutInflater li = LayoutInflater.from(getContext());
            v = li.inflate(R.layout.app_custom_list, null);
    
            holder = new ViewHolder();
            holder.titleText = (TextView)v.findViewById(R.id.titleTxt);
            v.setTag(holder);
        }
        else
           holder = (ViewHolder) v.getTag()
    
        Application app = items.get(position);
    
        if(app != null) {
    
            if(titleText != null) 
                holder.titleText.setText(app.getTitle());
    
        }
    
        return v;
    }
    
    
    static class ViewHolder { 
    
         TextView titleText;
    
    } 
    

    【讨论】:

    • 试过这段代码,它说convertView总是空的。
    • 对不起我的错误,应该是setTagsetTaggetTag中的v替换convertView,我刚刚修改了答案
    • 代码运行但我仍然只得到第一个name
    • 所以这可能是您的List&lt;Application&gt; items 问题,尝试调试以检查您的列表中有多少项目,也许只有一个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多