解析来自 JSON 服务器的数据时,Android ListView 不显示

Posted

技术标签:

【中文标题】解析来自 JSON 服务器的数据时,Android ListView 不显示【英文标题】:Android ListView not showing while parsing data from JSON server 【发布时间】:2015-11-24 02:08:07 【问题描述】:

所以我正在测试一个在 listview 上实现的 android 应用程序。该列表使用从 JSON 服务器获取的数据。视图中使用的三个字段是图像、名称、描述。我已经测试了所有输入,数据正确来自服务器,在适配器中设置(使用 LOG 标签检查),但应用程序没有显示任何视图,有时甚至崩溃。总之,我看不到任何列表视图。请帮忙... :)

这些是我的项目使用的文件...

MainActivity.java

package com.example.aditya.jtest;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;
import android.widget.Toast;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.IOException;
import java.util.ArrayList;


public class MainActivity extends Activity 

    ListView list;
    ActorsAdapter adapter;
    ArrayList<Actors> actorsList;


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

        list = (ListView) findViewById(R.id.list);
        actorsList = new ArrayList<Actors>();

        new        ActorsAsynTask().execute("http://microblogging.wingnity.com/JSONParsingTutorial/ `jsonActors");
        list.setAdapter(adapter);
    

    public class ActorsAsynTask extends AsyncTask<String, Void, Boolean> 

        ProgressDialog dialog;

        @Override
        protected void onPreExecute() 
        super.onPreExecute();
        dialog = new ProgressDialog(MainActivity.this);
        dialog.setMessage("Loading, please wait");
        dialog.setTitle("Connecting server");
        dialog.show();
        dialog.setCancelable(false);
    

        @Override
        protected Boolean doInBackground(String... params) 

            try 
                HttpClient client = new DefaultHttpClient();
                HttpPost post = new HttpPost(params[0]);
                HttpResponse response = client.execute(post);

                int status = response.getStatusLine().getStatusCode();
                //Log.d("MyFilter2", "" + status + "  Value Recieved: " + params[0]);

                if (status == 200) 
                    HttpEntity entity = response.getEntity();
                    String data = EntityUtils.toString(entity);
                    //Log.d("MyFilter", data);

                    JSONObject jObj = new JSONObject(data);
                    JSONArray jArray = jObj.getJSONArray("actors");
                    //Log.d("MyFilterjObj: ", jObj.toString());
                    //Log.d("MyFilterjArray: ", jArray.toString() + "\n" + jArray.length());

                    for(int i = 0; i <= jArray.length(); i++) 
                        Actors actors = new Actors();
                        JSONObject jRealObject = jArray.getJSONObject(i);
                        //Log.d("\nMyFilter JRealObject[" + i + "]: ", jRealObject.toString());

                        actors.setName(jRealObject.getString("name"));
                        actors.setDescription(jRealObject.getString("description"));
                        actors.setImage(jRealObject.getString("image"));

                        Log.d("\nMyFilter ["+ i +"]", jRealObject.getString("name"));
                        Log.d("MyFilter ["+ i +"]", jRealObject.getString("description"));
                        Log.d("MyFilter ["+ i +"]", jRealObject.getString("image"));

                        actorsList.add(actors);
                    
                    return true;
                

             catch (IOException e) 
                e.printStackTrace();
             catch (JSONException e) 
                e.printStackTrace();
            

            return false;
        

        @Override
        protected void onPostExecute(Boolean aBoolean) 
            super.onPostExecute(aBoolean);
            dialog.cancel();
            adapter.notifyDataSetChanged();

            if(aBoolean == false)
                //Show a message that data was not parsed
                Toast.makeText(getApplicationContext(), "Unable to fetch data from server", Toast.LENGTH_LONG).show();
            
        
    

Actor 适配器

package com.example.aditya.jtest;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class ActorsAdapter extends ArrayAdapter<Actors> 

ArrayList<Actors> ArrayListActors;
int Resource;
Context context;
LayoutInflater vi;
ViewHolder holder;


public ActorsAdapter(Context context, int resource, ArrayList<Actors> objects) 
    super(context, R.layout.row, objects);

    ArrayListActors = objects;
    Resource = resource;
    this.context = context;


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

    vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v = convertView;
    if(v == null)
        v = vi.inflate(Resource, null);
        holder = new ViewHolder();

        holder.image = (ImageView) convertView.findViewById(R.id.image);
        holder.name = (TextView) convertView.findViewById(R.id.name);
        holder.description = (TextView) convertView.findViewById(R.id.description);

        convertView.setTag(holder);
     else
        holder = (ViewHolder) convertView.getTag();
    

    new DownloadImageTask(holder.image).execute(ArrayListActors.get(position).getImage());
    holder.name.setText(ArrayListActors.get(position).getName());
    holder.description .setText(ArrayListActors.get(position).getDescription());

    return v;


static class ViewHolder
    public ImageView image;
    public TextView name;
    public TextView description;


private class DownloadImageTask extends AsyncTask<String, Void, Bitmap>

    ImageView bmImage;

    public DownloadImageTask(ImageView bmImage) 
        this.bmImage = bmImage;
    

    @Override
    protected Bitmap doInBackground(String... params) 
        String urlDisplay = params[0];
        Bitmap mIcon1 = null;
        try
            InputStream in = new java.net.URL(urlDisplay).openStream();
            mIcon1 = BitmapFactory.decodeStream(in);
         catch (MalformedURLException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        
        return mIcon1;
    

    @Override
    protected void onPostExecute(Bitmap bitmap) 
        bmImage.setImageBitmap(bitmap);
    

Actors.java

package com.example.aditya.jtest;

public class Actors 

private String image;
private String name;
private String description;

public Actors() 


public Actors(String name, String description, String image) 
    super();
    this.name = name;
    this.description = description;
    this.image = image;


public String getImage() 
    return image;


public void setImage(String image) 
    this.image = image;


public String getName() 
    return name;


public void setName(String name) 
    this.name = name;


public String getDescription() 
    return description;


public void setDescription(String description) 
    this.description = description;

【问题讨论】:

了解如何从服务器获取数据并设置列表视图here。 你的网址有效吗? 是的.. URL 正在工作...!! 【参考方案1】:

添加 onPostExecute() 的 ActorsAsynTask。

adapter = new ActorsAdapter(MainActivity.this, /*Your resource file id*/,actorsList);
list.setAdapter(adapter)

这样就可以了。

【讨论】:

不……不工作……应用程序崩溃了……一个问题 - 布局是否与它有任何关系……?? 我不这么认为..您只需要初始化适配器并将其设置为 onPostExecute() 中的列表视图。否则它将在后台进程完成之前执行,并且您可能有空列表视图或部分膨胀的列表视图。 不!......再次无法正常工作。我在 onPostExecute() 的“else”块中添加了上述两行。应用程序仍在崩溃... :( 在其他地方做。并告诉我 logcat 对错误的描述。 将代码移到其他地方......这是日志错误......进程:com.example.aditya.jtest,PID:4703 java.lang.NullPointerException at com.example .aditya.jtest.MainActivity$ActorsAsynTask.onPostExecute(MainActivity.java:110) 在 com.example.aditya.jtest.MainActivity$ActorsAsynTask.onPostExecute(MainActivity.java:44) 在 android.os.AsyncTask.finish(AsyncTask.java :632) 在 android.os.AsyncTask.access$600(AsyncTask.java:177)【参考方案2】:
 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.client.HttpClient;
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.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import android.widget.Toast;

public class PrivateJobList extends Fragment 

    /**Declaring the data members **/
    List<PrivateData> list;

    PrivateJobListAdapter adapter;

    ListView listview;

    PrivateJobList()

    

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) 
    

        View v=inflater.inflate(R.layout.private_job_list,container,false);

         listview=(ListView)v.findViewById(R.id.list);
         /*converting or say initializing list as arraylist*/
         list=new ArrayList<PrivateData>();

         /*instantiating the class which deals with fetching*/
     ExecuteTaskprivate executetask= new ExecuteTaskprivate();


         /*calling execute method on class instance*/
         executetask.execute();

         /*initializing the adapter*/
         adapter = new PrivateJobListAdapter(getActivity(),list);

        return v;
    


/*class to handle background task*/
class ExecuteTaskprivate extends AsyncTask<String, Void,String>


    @Override
    protected String doInBackground(String... params) 
        /**storing returned value from this method in res variable
         * and pass it to the postData method**/
        String res=postData(params);

        return res;
    


    /**This method Deals with the posting the client request
     * and storing the response in String variable which is 
     * nothing but a HttpResponse from the server**/
    private String postData(String[] params) 

        String s="";

        try  
          
        HttpClient httpClient=new DefaultHttpClient();

        HttpPost httpPost=new HttpPost("http://10.0.2.2/loginpage/private_jobs_fetching.php");  

        HttpResponse res=  httpClient.execute(httpPost);  

        @SuppressWarnings("unused")
        HttpEntity httpEntity=res.getEntity();  
        s= readResponse(res);  

          
        catch(Exception exception)    
        return s;  
    
/**this method returns String representation of response from server**/
private String readResponse(HttpResponse res) 
    String return_text="";

    InputStream is = null;
    try
     is=res.getEntity().getContent();  
     BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(is,"utf-8"),8);  
     String line="";  
     StringBuffer sb=new StringBuffer();  
     while ((line=bufferedReader.readLine())!=null)  
       
     sb.append(line);  
       


   return_text=sb.toString();
  catch (Exception e)  
   
      e.printStackTrace(); 
   
 return return_text;  


/**In onPostExecute String variable returned from doInBackground is used as parameter**/
@Override
protected void onPostExecute(String result) 
    super.onPostExecute(result);

    if(result.length()!=0)

    try 

        /**parsing JSONArray first**/
        JSONArray jArray = new JSONArray(result);
        /**looping through it's length**/
        for (int i = 0; i<jArray.length();i++) 
        
            /**And converting it to the JSONObject**/
            JSONObject json_data = jArray.getJSONObject(i);
            /**Creating instance of Bean class**/
            PrivateData user= new PrivateData();
            /**fetching data directly from server by providing column names
             * and setting to their respective setter method's of bean class**/
            user.setCompany_name(json_data.getString("company_name"));
            user.setJob_title(json_data.getString("job_title"));
            user.setLocation(json_data.getString("location"));
            user.setEmail(json_data.getString("email"));
            user.setUid(json_data.getInt("uid"));
            /**Adding PrivateData object to the list**/
            list.add(user);
        
         /**setting the adapter on listview**/
        listview.setAdapter(adapter);
     catch (JSONException e) 
        Log.e("log_tag", "Error parsing data " + e.toString());  
    

    
    else

        Toast.makeText(getActivity(), result, Toast.LENGTH_SHORT).show();
    





/**************************************************** *****************************/

/**Bean class with data members & their respective setter & getters**/
public class PrivateData 

    String company_name;

    String job_title;

    String location;

    String email;

    int uid;


    public String getCompany_name() 
        return company_name;
    

    public void setCompany_name(String company_name) 
        this.company_name = company_name;
    

    public String getJob_title() 
        return job_title;
    

    public void setJob_title(String job_title) 
        this.job_title = job_title;
    

    public String getLocation() 
        return location;
    

    public void setLocation(String location) 
        this.location = location;
    

    public String getEmail() 
        return email;
    

    public void setEmail(String email) 
        this.email = email;
    

    public int getUid() 
        return uid;
    

    public void setUid(int uid) 
        this.uid = uid;
    





/**************************************************** ************************************/

import java.util.List;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
/**ListAdapter class**/
public class PrivateJobListAdapter extends ArrayAdapter<PrivateData> 
    /**data members**/
    Context c;

    //int layout;

    List<PrivateData> list;



    /**Constructor**/
    public PrivateJobListAdapter(Context context,List<PrivateData> objects) 
        super(context,R.layout.row_view, objects);

        this.c=context;
        this.list=objects;

    


/**this method is used to display your fetched data from server **/
    @Override
    public View getView(int position, View convertView, ViewGroup parent) 

         View row = convertView;
         /**initializing class which has all textview required for showing column data
          * of table on server**/
         UserHolder holder = null;

         if(row==null)
             /**this is important step if your main class is an Activity
              * then write it as 
              * LayoutInflater inflater = ((Activity) context).getLayoutInflater();
              * and import android.app.activity**/
             LayoutInflater inflater= LayoutInflater.from(c);
             /****/
             row = inflater.inflate(R.layout.row_view, parent, false);
               holder = new UserHolder();

               holder.textcompanyname=(TextView) row.findViewById(R.id.textview_company_name);

               holder.textjobtitle=(TextView) row.findViewById(R.id.textview_job_title);

               holder.textlocation=(TextView) row.findViewById(R.id.textview_location);

               holder.textemail=(TextView) row.findViewById(R.id.textview_email);


               /**setting tag**/
               row.setTag(holder);

         
         else 
             /**getting tag**/
               holder = (UserHolder) row.getTag();
              


        return row;
    

    static class UserHolder 
          TextView textcompanyname;
          TextView textjobtitle;
          TextView textlocation;
          TextView textemail;


         

/**************************************************** ******/

//private_job_list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >

 <TextView android:id="@+id/textview_private_job_list"
        android:layout_
        android:layout_
        android:background="@drawable/button_rounded"
        android:layout_marginTop="20dp"
        android:layout_marginStart="32dp"
        android:text="@string/private_job_list_text"
        android:textSize="20sp"
        android:gravity="center"/>


 <ListView 

     android:id="@+id/list"

     android:layout_
     android:layout_></ListView>



</LinearLayout>

/**********************************************/

//row-view.xml


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_ >


    <TextView
        android:id="@+id/textview_company_name"
        android:layout_
        android:layout_
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:text="@string/company_name"
        android:textSize="18sp"/>

    <TextView
        android:id="@+id/textview_job_title"
        android:layout_
        android:layout_
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textview_company_name"
        android:layout_marginTop="5dp"
        android:text="@string/job_title"
        android:textSize="18sp" />

    <Button
        android:id="@+id/button_more"
        android:layout_
        android:layout_
        android:layout_alignParentEnd="true"
        android:layout_marginTop="40dp"
        android:background="@drawable/button_rounded"
        android:focusable="false"
        android:focusableInTouchMode="false"
        android:text="@string/btn_more"
        android:textColor="#0099CC" />



    <TextView
        android:id="@+id/textview_location"
        android:layout_
        android:layout_
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textview_job_title"
        android:layout_marginTop="5dp"
        android:text="@string/location"
        android:textSize="18sp"/>


    <TextView
        android:id="@+id/textview_email"
        android:layout_
        android:layout_
        android:layout_alignParentStart="true"
        android:layout_below="@+id/textview_location"
        android:layout_marginTop="5dp"
        android:text="@string/email"
        android:textSize="18sp" />




</RelativeLayout>

/************************************************/

//button_rounded.xml


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">

    <solid android:color="#ec0b47"/>
    <corners
        android:radius="30dp"/>    

</shape>

/****************************************/

//php code


<?php

$host='localhost:3306';
$uname='root';
$pwd='';
$db="mydb";

$connection=mysqli_connect($host,$uname,$pwd,$db);
$database=mysqli_select_db($connection,$db);

$query1=mysqli_query($connection,"SELECT  * FROM  private_jobs");


while($row=mysqli_fetch_assoc($query1))


    $result[]=$row;


print(json_encode($result));

mysqli_close($connection);

?>



happy coding!!!!

【讨论】:

以上是关于解析来自 JSON 服务器的数据时,Android ListView 不显示的主要内容,如果未能解决你的问题,请参考以下文章

无法解析来自服务器的 JSON 数据

解析 JSON 并在 Listview 中显示检索/获取 URL 服务器“无数据”

Android:如何让我检索到的(来自 mysql)JSON 解析数据添加到 ListView 每分钟刷新一次

Android – 使用带有 Jetpack Compose 的 Retrofit 库进行 JSON 解析

Android – 使用带有 Jetpack Compose 的 Retrofit 库进行 JSON 解析

Android – 使用带有 Jetpack Compose 的 Retrofit 库进行 JSON 解析