为什么适配器要多次向ListView添加相同的位置?

时间:2022-08-31 08:45:30

为什么适配器要多次向ListView添加相同的位置?

Not sure how clear it may be, but the issue I am having is that my adaptor is adding the same position from a TreeMap multiple times. This shouldn't be happening/ It's adding the same movie multiple times.

我不确定它可能有多清晰,但我遇到的问题是我的适配器多次从TreeMap添加相同的位置。这是不应该发生的。

I have looked at the code and tried to follow the cycle of the code but I just can't seem to find the problem.

我查看了代码并尝试遵循代码的循环,但是我似乎无法找到问题。

I have made Gists of my code as it's too long and I don't want to spam the page.

由于我的代码太长了,所以我已经对它进行了修改,我不想在页面上发垃圾邮件。

If you guys really want it all on here I will update my question.

如果你们真的想知道,我会更新我的问题。

My application makes requests to an API and gets a TreeMap of movie ids, titles, info, posters... and so on. This particular problem is with my ListViewAdaptor.

我的应用程序向API发出请求,并获得电影id、标题、信息、海报的TreeMap…等等。这个特殊的问题是我的ListViewAdaptor。

MainActivityFragment.java

MainActivityFragment.java

ListViewAdaptor.java

ListViewAdaptor.java

MainActivity.java

MainActivity.java

fragment_main.xml

fragment_main.xml

activity_main.xml

activity_main.xml

results_layout.xml

results_layout.xml

HttpHandler.java

HttpHandler.java

ListViewAdaptor

ListViewAdaptor

package com.example.zdroa.fetchmovies;

import android.content.Context;
import android.graphics.drawable.Drawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

import java.util.TreeMap;

class ListViewAdaptor extends BaseAdapter {

    private Context mContext;
    private TreeMap<Integer, String> urls;
    private TreeMap<Integer, String> titles;

    ListViewAdaptor(Context context, TreeMap<Integer, String> URLS, TreeMap<Integer, String> TITLES) {
        mContext = context;
        urls = URLS;
        titles = TITLES;
    }

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

    @Override
    public Object getItem(int position) {
        return null;
    }

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

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

        if (convertView == null) {
            convertView = View.inflate(mContext, R.layout.results_layout, null);
        }
        ImageView imageView = (ImageView) convertView.findViewById(R.id.ivPosters);
        TextView textView = (TextView) convertView.findViewById(R.id.results_layout_tv_movie_name);

        Drawable d = mContext.getResources().getDrawable(R.drawable.place_holder_img);


        String link_end = urls.ceilingEntry(position).getValue();
        String title = titles.ceilingEntry(position).getValue();

        Picasso.with(mContext)
                .load("http://image.tmdb.org/t/p/w185" + link_end)
                .placeholder(d)
                .into(imageView);

        textView.setText(title);


        return convertView;
    }
}

MainActivityFragment.java

MainActivityFragment.java

package com.example.zdroa.fetchmovies;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ListView;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.TreeMap;

public class MainActivityFragment extends Fragment {

    private static String API_KEY = "b692b9da86f1cf0c1b623ea6e2770101";

    ListView listView;
    Button button;

    static TreeMap<Integer, Integer> IDS;
    static TreeMap<Integer, String> TITLES;
    static TreeMap<Integer, String> POSTERS;
    static TreeMap<Integer, String> GENRES;
    static TreeMap<Integer, String> PRODUCTION_COUNTRIES;
    static TreeMap<Integer, String> OVERVIEW;
    static TreeMap<Integer, String> RUNTIME;

    public MainActivityFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_main, container, false);

        listView = (ListView) rootView.findViewById(R.id.lvMovies);

        new ImageLoadTask().execute();

        //if fragment is visible
        if (getActivity() != null) {


            listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {

                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    System.out.println(TITLES.ceilingEntry(position).getValue());
                }
            });
        }
        return rootView;
    }

    @Override
    public void onStart() {
        super.onStart();

    }

    private class ImageLoadTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) {

            IDS = new TreeMap<>();

            IDS.put(1, 2);
            IDS.put(2, 3);
            IDS.put(3, 5);
            IDS.put(4, 6);
            IDS.put(5, 8);
            IDS.put(6, 9);
            IDS.put(7, 11);
            IDS.put(8, 12);
            IDS.put(9, 13);
            IDS.put(10, 14);


            populateTreeMaps();


            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            if (getActivity() != null) {
                ListViewAdaptor adapter = new ListViewAdaptor(getActivity(), POSTERS, TITLES);
                listView.setAdapter(adapter);

                System.out.println(POSTERS);
                System.out.println(TITLES);
            }
        }

        private Void populateTreeMaps() {
            HttpHandler httpHandler = new HttpHandler();

            TITLES = new TreeMap<>();
            POSTERS = new TreeMap<>();

            for (int i = 0; i < IDS.size(); i++) {
                String jsonString = httpHandler.makeServiceCall("https://api.themoviedb.org/3/movie/" + IDS.ceilingEntry(i).getValue() + "?api_key=" + API_KEY);

                if (jsonString != null) {
                    try {
                    //POPULATE ALL THE GRAPHS HERE
                        getTitles(jsonString, IDS.ceilingEntry(i).getValue());
                        getPosterURLs(jsonString, IDS.ceilingEntry(i).getValue());

                    } catch (JSONException e) {
                        return null;
                    }
                }
            }
            return null;
        }

        private void getTitles(String JSONString, Integer mov_id) throws JSONException {
            JSONObject jsonObject = new JSONObject(JSONString);

            String title = jsonObject.getString("title");

            TITLES.put(mov_id, title);
        }

        private void getPosterURLs(String JSONString, Integer mov_id) throws JSONException {
            JSONObject jsonObject = new JSONObject(JSONString);

            String url = jsonObject.getString("poster_path");

            POSTERS.put(mov_id, url);
        }

        private void getYoutubeLink() {
        }
    }
}

2 个解决方案

#1


2  

There's a problem with your key->value logic.

您的key->值逻辑有一个问题。

You're using TreeMap filled with keys that have gaps [2,3,5,6, etc], then in adapter you try to get item by position, obviously your map doesn't contain item for every position you want, so your ceilingEntry() returns next item with key >= requested_key

您正在使用TreeMap填充具有间隔的键[2、3、5、6等],然后在适配器中尝试按位置获取项,显然您的映射没有包含您想要的每个位置的项,因此,您的ceilingEntry()返回下一个项,键>= requested_key

See this for clarification: https://www.tutorialspoint.com/java/util/treemap_ceilingentry.htm

请参见下面的说明:https://www.tutorialspoint.com/java/util/treemap_ingentry.htm

Simplest and most straight forward solution would be to move to List<Movie> where Movie is a new model class that contains all data you need to display (url, title, ..) in your adapter.

最简单和最直接的解决方案是移动到List ,其中Movie是一个新的模型类,它包含您需要在适配器中显示的所有数据(url, title, .. .)。

#2


2  

Try this: Implement the following two method thw following way in the ListViewAdaptor class:

试试这个:在ListViewAdaptor类中实现以下两种方法:

 @Override
public Object getItem(int position) {
    return urls.get(position);
}

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

#1


2  

There's a problem with your key->value logic.

您的key->值逻辑有一个问题。

You're using TreeMap filled with keys that have gaps [2,3,5,6, etc], then in adapter you try to get item by position, obviously your map doesn't contain item for every position you want, so your ceilingEntry() returns next item with key >= requested_key

您正在使用TreeMap填充具有间隔的键[2、3、5、6等],然后在适配器中尝试按位置获取项,显然您的映射没有包含您想要的每个位置的项,因此,您的ceilingEntry()返回下一个项,键>= requested_key

See this for clarification: https://www.tutorialspoint.com/java/util/treemap_ceilingentry.htm

请参见下面的说明:https://www.tutorialspoint.com/java/util/treemap_ingentry.htm

Simplest and most straight forward solution would be to move to List<Movie> where Movie is a new model class that contains all data you need to display (url, title, ..) in your adapter.

最简单和最直接的解决方案是移动到List ,其中Movie是一个新的模型类,它包含您需要在适配器中显示的所有数据(url, title, .. .)。

#2


2  

Try this: Implement the following two method thw following way in the ListViewAdaptor class:

试试这个:在ListViewAdaptor类中实现以下两种方法:

 @Override
public Object getItem(int position) {
    return urls.get(position);
}

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