ListView:使用 JSON 中的图像填充列表视图

ListView: Populate listview with images from JSON

我有一个列表视图,在通过 Php/JSON 显示数据库中的所有文本时,它工作得很好。但是,在数据库中有一个图像 link 与我想在列表视图中显示的每个项目相关联。基本上它的作用是当一个人点击搜索按钮时,操作菜单中默认的 android 搜索栏出现在他们输入单词的地方。然后它转到服务器并发送单词并尝试从数据库中找到所有匹配项并将其拉出。现在它可以完美地显示文本视图,但由于某种原因我无法显示图像。有人可以告诉我怎么做吗?我尝试了几次但都失败了,因此我提供给您的代码是我的最新代码:

public class ListResult extends ListActivity {

    // Progress Dialog
    private ProgressDialog pDialog;

    // Creating JSON Parser object
    JSONParser jParser = new JSONParser();

    ArrayList<HashMap<String, String>> UserBooksList;

    // url to get the idiom list
    private static String url_search =   
    "http://randomurl.com/arandomapp/search.php";

    // JSON Node names
    private static final String TAG_SUCCESS = "success";
    private static final String TAG_UserBooks = "UserBooks";
    private static final String TAG_BName = "BName";
    private static final String TAG_NAME = "name";

    // THIS TAG BELOW IS THE ONE WHICH SHOWS THE IMAGE URL.
    private static final String TAG_IMG = "Id";

    // products JSONArray
    JSONArray user_books = null;

    // The keyword send to server and displays the result.
    public String search_key;

    TextView mError;

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

    // get the action bar
    ActionBar actionBar = getActionBar();
    actionBar.setDisplayHomeAsUpEnabled(true);

    if (savedInstanceState == null) {
        Bundle extras = getIntent().getExtras();
        if(extras == null) {
            search_key = null;
        } else {
            search_key = extras.getString("keyword");
        }
    } else {
        search_key = (String) savedInstanceState.getSerializable("keyword");
    }

    UserBooksList = new ArrayList<>();

    // Loading idioms in Background Thread
    new LoadIdioms().execute();

    mError = (TextView) findViewById(R.id.error);
    mError.setVisibility(View.GONE);

    actionBar.setTitle("Relevant Searches For: " + search_key);
    actionBar.setIcon(R.drawable.ic_action_search);
}

class LoadIdioms extends AsyncTask<String, String, String> {

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(ListResult.this);
        pDialog.setMessage("Loading Data. Please wait...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();
    }

    protected String doInBackground(String... args) {

        // Building Parameters
        List<NameValuePair> params = new ArrayList<>();

        //value captured from previous intent
        params.add(new BasicNameValuePair("keyword", search_key));

        // getting JSON string from URL
        JSONObject json = jParser.makeHttpRequest(url_search, "GET",    
params);

        try {

            int success = json.getInt(TAG_SUCCESS);

            if (success == 1) {

                user_books = json.getJSONArray(TAG_UserBooks);

                for (int i = 0; i < user_books.length(); i++) {
                    JSONObject c = user_books.getJSONObject(i);

                    // Storing each json item in variable
                    String bName = c.getString(TAG_BName);
                    String Name = c.getString(TAG_NAME);
                    String b_img = c.getString(TAG_IMG);

                    // creating new HashMap
                    HashMap<String, String> map = new HashMap<>();

                    // adding each child node to HashMap key => value
                    map.put(TAG_BName, bName);
                    map.put(Tag_NAME, Name);
                    map.put(TAG_IMG, b_img);

                    // adding HashList to ArrayList
                    UserBooksList.add(map);

                }
            } else {
                Log.d("Login Failure!", json.getString(TAG_MESSAGE));
                return json.getString(TAG_MESSAGE);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

    protected void onPostExecute(String file_url) {

        // dismiss the dialog after getting the related idioms
        pDialog.dismiss();

        // updating UI from Background Thread
        runOnUiThread(new Runnable() {

            public void run() {
                /**
                 * Updating parsed JSON data into ListView
                 **/

                ListAdapter adapter = new SimpleAdapter(
                        ListResult.this, UserBooksList,
                        R.layout.list_item, new String[] {TAG_BName, TAG_Name},
                        new int[] {R.id.BName, R.id.Name});

                // updating listview
                setListAdapter(adapter);
            }
        });

        // dismiss the dialog once product deleted
        pDialog.dismiss();
        if (file_url != null){
            mError = (TextView) findViewById(R.id.error);
            mError.setVisibility(View.VISIBLE);
            mError.setText("Sorry, No Books were found. Please try again.");
        }
    }
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
    inflater.inflate(R.menu.activity_main_actions_two, menu);

    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Take appropriate action for each action item click
    switch (item.getItemId()) {
        case R.id.action_help:
            // help action
            return true;
        default:
            return super.onOptionsItemSelected(item);
    }
}
}

任何人都可以建议我如何结合在加载图像时同时设置图像的想法吗?我的意思是当我尝试时,图像的 url 被完美地获取了。

我有一个 list_item.xml,其中包含名称的 textview 和一个 id 为:ImageView3 的 imageView。

谢谢 :)

Picasso Library个。它处理异步图像获取、淡入淡出动画、缓存并且非常易于使用。

正如 Johan 所建议的那样,使用 Picasso Library。并且您需要将图像 url 绑定到适配器的 getview 方法中的图像视图。

同样在你的 onPostExecute 方法中,你不需要在 runonuithread 方法中编写代码,因为 onPostExecute 方法本身在 ui 线程上运行。

最好使用 Java 中的对象,因此首先使用以下代码创建一个名为 UserBook 的新 class :

public class UserBook {

private String name;
private String BName;
private String imageUrl;

public UserBook() {
}

public String getName() {
    return name;
}

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

public String getBName() {
    return BName;
}

public void setBName(String BName) {
    this.BName = BName;
}

public String getImageUrl() {
    return imageUrl;
}

public void setImageUrl(String imageUrl) {
    this.imageUrl = imageUrl;
}
}

现在列表中的 ArrayList activity 像这样启动它:

private ArrayList<UserBook> userBooksList;

填充我们的数组列表很容易,只需创建一个新的 UserBook 对象并将其放入我们的数组中即可:

    UserBook book = new UserBook();

    book.setName(Name);
    book.setBName(bName);
    book.getImageUrl(b_img);

    userBookList.add(book);

创建一个新的 XML 布局文件并将其命名为 cell。这将是我们的自定义单元格,我们的适配器将使用它来在列表视图中显示数据。

<?xml version="1.0" encoding="utf-8"?>

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/cell_imageView" />

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:text="Medium Text"
        android:id="@+id/cell_textView" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:text="Small Text"
        android:id="@+id/cell_textView2" />
</LinearLayout>

所以最重要的部分来了,我们的列表视图的自定义适配器。创建一个新的 class 并将其命名为 MyCustomAdapter :

public class MyCustomAdapter extends ArrayAdapter<UserBook> {

Context context;

public MyCustomAdapter(Context context, int resource, ArrayList<UserBook> books) {
    super(context, resource, books);

  //UPDATE!!!!
  this.context = context;

}


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

    Holder holder;

    //First we check if the cell is being created for the first time, if its the case we inflate from
    //our xml

    if (cell == null){

        holder = new Holder();

        //get the xml inflator service
        LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        //Fill our cell with the xml
        cell = inflater.inflate(R.layout.cell, null);

        //Fill our holder with components
        holder.imageView = (ImageView)cell.findViewById(R.id.cell_imageView);
        holder.textView = (TextView)cell.findViewById(R.id.cell_textView);
        holder.textView2 = (TextView)cell.findViewById(R.id.cell_textView2);

        //this is very important..here we are attaching the holder to the current row
        cell.setTag(holder);
    }else{

        //the cell was created before so we can grab the holder attached
        holder = (Holder)cell.getTag();
    }

    //get current book item
    UserBook book = getItem(position);

    //fill data
    holder.textView.setText(book.getName());
    holder.textView2.setText(book.getBName());

    //set picasso
    Picasso.with(context).load(Uri.parse(book.getImageUrl())).into(holder.imageView);

    return cell;
}

//The holder will hold the inflated views and attach them to the listview's row
//for performance
private class Holder{

    ImageView imageView;
    TextView textView;
    TextView textView2;

}

}

要简单地使用我们的自定义适配器:

 MyCustomAdapter adapter = new MyCustomAdapter(context, R.layout.cell, userBookList);

    listView.setAdapter(adapter);

请研究这个,我可以提供帮助,因为这是 Android 中处理列表视图的最佳实践