【问题标题】:ListView: Populate listview with images from JSONListView:使用来自 JSON 的图像填充列表视图
【发布时间】:2015-02-21 03:07:31
【问题描述】:

我有一个列表视图,它在通过 Php/JSON 显示数据库中的所有文本时效果很好。但是,在数据库中有一个与我想在列表视图中显示的每个项目相关联的图像链接。基本上它的作用是一个人单击搜索按钮,然后在他们输入单词的位置出现操作菜单中的默认 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,其中包含名称的文本视图和一个 ID:ImageView3 的 imageView。

谢谢:)

【问题讨论】:

    标签: php android json listview android-listview


    【解决方案1】:

    在 Java 中使用对象是一种很好的做法,因此首先使用以下代码创建一个名为 UserBook 的新类:

    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 像这样启动它:

    private ArrayList<UserBook> userBooksList;
    

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

        UserBook book = new UserBook();
    
        book.setName(Name);
        book.setBName(bName);
        book.getImageUrl(b_img);
    
        userBookList.add(book);
    

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

    <?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>
    

    所以这里是最重要的部分,我们的列表视图的自定义适配器。创建一个新的类名 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 中处理列表视图的最佳实践

    【讨论】:

    • 最重要的部分。我将如何继续从 URL 获取 json 响应?我什么都没看到? :p 我没有得到用户手册类的想法?我的意思是我肯定会创建那个类,但是在用户提交单词后,文本来自那个 search.php 的 json 格式。 :p
    • 你获取json对象的代码很好,你替换部分:map.put(TAG_BName, bName); map.put(Tag_NAME, 名称); map.put(TAG_IMG, b_img);用这个 > book.setName(Name); book.setBName(bName); book.getImageUrl(b_img); userBookList.add(book);
    • 对,所以我添加了代码:对于 listview.setAdapter(adapter);我将其更改为: lv.setAdapter(adapter);因为如果你看一下上面的代码,我已经有一个 ListView lv = getListView();。至于: yCustomAdapter adapter = new MyCustomAdapter(context,... context 部分给出错误提示:无法解析为符号“context”。
    • 如果我像这样创建上面的值:Context context = null;错误消失了。那会发现将上下文初始化为null吗?
    • context = getApplicationContext();
    【解决方案2】:

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

    【讨论】:

    • 错误:致命异常:AsyncTask #2 将代码置于:map.put(Tag_NAME, Name); map.put(TAG_IMG, b_img); UserBooksList.add(map); ImageView imageView = (ImageView) findViewById(R.id.imageView3); Picasso.with(ListResult.this) .load(b_img) .into(imageView); 我确实提到它不是一个图像,对吧?它是一组图像,将显示在已存储 url 的数据库中的列表视图中。
    • 我建议您创建自己的自定义适配器,您需要帮助吗?
    • 适配器,你的意思是ImageLoader吗?因为如果您谈论实际的 CustomAdapter.class,那么我没有它。我基本上遵循了本教程,它没有使用任何适配器类。 Search Operation on Android Online
    • 我肯定需要有关如何执行此操作的帮助,因为我还是自定义适配器类理念的新手:P,我非常感谢您提前提供的帮助 :)
    • 亲爱的先生,请把你的json回复发给我,我会帮你找到最好的解决方案
    【解决方案3】:

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

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

    【讨论】:

    • 我厌倦了它,它给了我一个致命的错误。随意看看我上面的回复。如何绑定 Imageview?当您说适配器时,您是指毕加索随附的适配器还是我自己的适配器?
    猜你喜欢
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多