Picasso Returns 将图像 URL 加载到 ImageView 时出错

Picasso Returns Error when Loading Image URL into ImageView

我正在尝试从 RecyclerView 的适配器 class 将图像 URL 字符串加载到 ImageView 中,并且我正在显示 RecyclerViewFragment 中。但是,当使用 Picasso 代码加载 URL 时,ImageView 中没有显示任何内容。我尝试放置上下文,this.main.getActivity()this.main.getContext()this.main.getActivity().getApplicationContext()。没有任何效果。

public class NewsAdapter extends RecyclerView.Adapter<NewsHolder> {

OneFragment main;
private Context context;
LayoutInflater inflater;
private ArrayList<Latest_News> arraylist;
private int itemResource;


public NewsAdapter(Context context, OneFragment main, ArrayList<Latest_News> arraylist)
{
    this.context = context;
    this.main = main;
    inflater = LayoutInflater.from(context);
    this.arraylist = arraylist;
}


@Override
public NewsHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
    View view = LayoutInflater.from(viewGroup.getContext())
            .inflate(R.layout.news_cell, viewGroup, false);

    return new NewsHolder(this.context, view);
}

@Override
public void onBindViewHolder(final NewsHolder newsHolder, int i) {

    Latest_News news = this.arraylist.get(i);

    Picasso.with(context)
            .load(news.getNewsImageURL())
            .into(newsHolder.newsImage);

}

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

@Override
public int getItemCount() {

    return this.arraylist.size();
}

}

这是我的 ViewHolder 的代码,我把它命名为 NewsHolder:

public class NewsHolder extends RecyclerView.ViewHolder implements View.OnClickListener {

public TextView subject;
public ImageView newsImage;

private Latest_News news;
private Context context;

public LinearLayout linearLayout;

ProgressBar progressBar;

public NewsHolder(Context context, View itemView) {

    super(itemView);

    // 1. Set the context
    this.context = context;

    // 2. Set up the UI widgets of the holder

    linearLayout = (LinearLayout) itemView.findViewById(R.id.linearLayout);
    this.subject = (TextView) itemView.findViewById(R.id.subject);
    this.newsImage = (ImageView) itemView.findViewById(R.id.newsImage);

    if (itemView != null) {
        progressBar = (ProgressBar) itemView.findViewById(R.id.progressBar);
        //progressBar.setVisibility(View.VISIBLE);
    }

    final Typeface tvFont = Typeface.createFromAsset(context.getAssets(), "fonts/FSMatthew-Medium.otf");
    this.subject.setTypeface(tvFont);

    // 3. Set the "onClick" listener of the holder
    itemView.setOnClickListener(this);
}

public void bindBakery(Latest_News news) {

    // 4. Bind the data to the ViewHolder
    this.news = news;
    this.subject.setText(news.subject);

    //load the image url with a callback to a callback method/class
    String iconUrl = news.getNewsImageURL();
}

@Override
public void onClick(View v) {

    // 5. Handle the onClick event for the ViewHolder
    if (this.news != null) {

        Toast.makeText(this.context, "Clicked on " + this.news.subject, Toast.LENGTH_SHORT ).show();
    }
}

private class ImageLoadedCallback implements Callback {
    ProgressBar progressBar;

    public  ImageLoadedCallback(ProgressBar progBar){
        progressBar = progBar;
    }

    @Override
    public void onSuccess() {

    }

    @Override
    public void onError() {

    }
}


}

这是我的数据模型的class,我称之为Latest_News:

public class Latest_News {
public String subject;
public String body;
public String image_url;
public String news_url;


public Latest_News(String subject, String body, String image_url, String news_url) {
    this.subject = subject;
    this.body = body;
    this.image_url = image_url;
    this.news_url = news_url;
}

public Latest_News() {
}

public String getNewsSubject() {
    return this.subject;
}

public String getNewsBody() {
    return this.body;
}

public String getNewsImageURL() {
    return this.image_url;
}

public String getNewsURL() {
    return this.news_url;
}
}

这是我的片段的class,我称之为OneFragment:

public class OneFragment extends Fragment implements Download_data.download_complete {

RecyclerView listView;
public NewsAdapter adapter;

private static View view;

RecyclerView.LayoutManager layoutManager;

private ProgressBar spinner;

public static ArrayList<Latest_News> news;
public static ArrayList<Latest_News> news_sort;



public OneFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

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

    spinner = (ProgressBar)view.findViewById(R.id.progressBar1);
    spinner.setVisibility(View.VISIBLE);

    news = new ArrayList<>();
    news_sort = new ArrayList<>();

    adapter = new NewsAdapter(getActivity(), this, news);
    //adapter = new ListAdapter(getContext(), R.layout.stations_cell, stations);


    // 4. Initialize ItemAnimator, LayoutManager and ItemDecorators
    layoutManager = new LinearLayoutManager(getActivity());

    int verticalSpacing = 40;
    VerticalSpaceItemDecorator itemDecorator =
            new VerticalSpaceItemDecorator(verticalSpacing);
    ShadowVerticalSpaceItemDecorator shadowItemDecorator =
            new ShadowVerticalSpaceItemDecorator(getActivity(), R.drawable.drop_shadow);


     // 5. Setup our RecyclerView
    listView = (RecyclerView)view.findViewById(R.id.listings_view);



     // 6. For performance, tell OS RecyclerView won't change size
    listView.setHasFixedSize(true);

    // 7. Set the LayoutManager
    listView.setLayoutManager(layoutManager);

     // 8. Set the ItemDecorators
    listView.addItemDecoration(shadowItemDecorator);
    listView.addItemDecoration(itemDecorator);

    // 9. Attach the adapter to RecyclerView
    listView.setAdapter(adapter);


    additems();
    adapter.notifyDataSetChanged();

    // Inflate the layout for this fragment
    return view;
}

public void additems() {


    Download_data download_data = new Download_data((Download_data.download_complete) this);

    String apiURL = String.format("https://example.com/API/latestnews/1");

    download_data.download_data_from_link(apiURL);

    Log.d("myTag", "dafdewfewffe" + adapter.getItemCount());

}



public void get_data(String data)
{

    try {
        JSONArray data_array=new JSONArray(data);

        for (int i = 0 ; i < data_array.length() ; i++)
        {
            JSONObject obj=new JSONObject(data_array.get(i).toString());

            Latest_News developers = new Latest_News(obj.getString("subject"), obj.getString("body"), obj.getString("image_url"), obj.getString("news_url"));
            news.add(developers);
            spinner.setVisibility(View.GONE);

        }

        adapter = new NewsAdapter(getActivity(), this, news);
        listView.setAdapter(adapter);
        adapter.notifyDataSetChanged();

    } catch (JSONException e) {
        e.printStackTrace();
    }

}

}

您的代码似乎没问题。

检查您的设备互联网连接,如果没问题,请检查您正在尝试加载的 url,看看它是否正常工作。

提示:不要每次都通过将字体放在 ViewHolder 中来创建字体,而是创建一次字体,将其设为静态并每隔一段时间使用一次

问题是 Picasso 不接受加载 http URL。我是这样解决的:

首先我在 gradle 文件中编译了以下内容以及我之前已经编译过的 Picasso 库:

implementation 'com.squareup.picasso:picasso:2.5.2'
implementation 'com.squareup.okhttp:okhttp:2.2.0'
implementation 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'

然后我创建了以下 class:

public class PicassoTrustAll {

private static Picasso mInstance = null;

private PicassoTrustAll(Context context) {
    OkHttpClient client = new OkHttpClient();
    client.setHostnameVerifier(new HostnameVerifier() {
        @Override
        public boolean verify(String s, SSLSession sslSession) {
            return true;
        }
    });
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
        @Override
        public void checkClientTrusted(
                java.security.cert.X509Certificate[] x509Certificates,
                String s) throws java.security.cert.CertificateException {
        }

        @Override
        public void checkServerTrusted(
                java.security.cert.X509Certificate[] x509Certificates,
                String s) throws java.security.cert.CertificateException {
        }

        @Override
        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return new java.security.cert.X509Certificate[] {};
        }
    } };
    try {
        SSLContext sc = SSLContext.getInstance("TLS");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        client.setSslSocketFactory(sc.getSocketFactory());
    } catch (Exception e) {
        e.printStackTrace();
    }

    mInstance = new Picasso.Builder(context)
            .downloader(new OkHttpDownloader(client))
            .listener(new Picasso.Listener() {
                @Override
                public void onImageLoadFailed(Picasso picasso, Uri uri, Exception exception) {
                    Log.e("PICASSO", String.valueOf(exception));
                }
            }).build();

}

public static Picasso getInstance(Context context) {
    if (mInstance == null) {
        new PicassoTrustAll(context);
    }
    return mInstance;
}
}

这就是我在 Adapter 中使用 Picasso 的方式 class:

PicassoTrustAll.getInstance(context)
            .load(news.getNewsImageURL())
            .into(newsHolder.newsImage);

感谢@RamchandraSingh