Я создал просмотр списка, который извлекает данные json с сервера, который содержит URL для извлечения изображения для каждой строки, я использую Picasso для установки изображений, но когда я прокручиваю просмотр списка, он обновляет изображения и иногда просто не ставит их в правильное положение при первой загрузке. вот мой код адаптера:
public class drugs_adaptor_listView extends ArrayAdapter<drugs_json_data> {
ArrayList<drugs_json_data> drugs;
Context context;
int resource;
public drugs_adaptor_listView(Context context, int resource, ArrayList<drugs_json_data> drugs) {
super(context, resource, drugs);
this.drugs = drugs;
this.context = context;
this.resource = resource;
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View r = convertView;
ViewHolder viewHolder;
if(r == null) {
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
r = layoutInflater.inflate(R.layout.row_layout_drugs, null, true);
viewHolder = new ViewHolder(r);
r.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) r.getTag();
}
drugs_json_data drugs_json_data = getItem(position);
viewHolder.txtDrugId.setText(drugs_json_data.getDrugId());
viewHolder.txtDrugName.setText(drugs_json_data.getDrugName());
viewHolder.txtDrugCategory.setText(drugs_json_data.getDrugCategory());
Picasso builder = new Picasso.Builder(context).memoryCache(new LruCache(24000)).build();
builder.load(drugs_json_data.getDrugImage()).placeholder(R.drawable.ic_launcher_foreground).into(viewHolder.imageView);
return r;
}
class ViewHolder{
TextView txtDrugId, txtDrugName, txtDrugCategory;
ImageView imageView;
ViewHolder(View v){
txtDrugId = v.findViewById(R.id.txtDrugId);
txtDrugName = v.findViewById(R.id.txtDrugName);
txtDrugCategory = v.findViewById(R.id.txtDrugCat);
imageView = v.findViewById(R.id.ImageViewDrug);
}
}
}
и это код действия (только соответствующие части):
publi c класс clerk_drugs extends AppCompatActivity {
ListView listView;
Button createDrug;
String drug_id, json_drug;
TextView noMed;
EditText searchTxt;
JSONObject jsonObject;
JSONArray jsonArray;
ArrayList<drugs_json_data> arrayList;
drugs_adaptor_listView adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_clerk_drugs);
createDrug = findViewById(R.id.create_drug);
arrayList = new ArrayList<>();
listView = findViewById(R.id.list_drugs);
noMed = findViewById(R.id.no_med);
searchTxt = findViewById(R.id.listSearch);
runOnUiThread(new Runnable() {
@Override
public void run() {
try {
new ReadJSON().execute("http://(the php file link)").get();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
class ReadJSON extends AsyncTask<String, Integer, String>{
@Override
protected String doInBackground(String... params) {
return readURL(params[0]);
}
@Override
protected void onPostExecute(String content) {
try {
JSONObject jsonObject = new JSONObject(content);
JSONArray jsonArray = jsonObject.getJSONArray("server_response");
for(int i=0; i<jsonArray.length();i++){
JSONObject drugObj = jsonArray.getJSONObject(i);
arrayList.add(new drugs_json_data(
drugObj.getString("drug_photo"),
drugObj.getString("drug_name"),
drugObj.getString("drug_category"),
drugObj.getString("drug_id")
));
}
} catch (JSONException e) {
e.printStackTrace();
}
adapter = new drugs_adaptor_listView(
getApplicationContext(), R.layout.row_layout_drugs, arrayList
);
listView.setAdapter(adapter);
listView.setTextFilterEnabled(true);
if (adapter.getCount()==0){
noMed.setVisibility(View.VISIBLE);
}
}
}
private String readURL(String theURL) {
StringBuilder content = new StringBuilder();
try{
URL url = new URL(theURL);
URLConnection urlConnection = url.openConnection();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
while((line=bufferedReader.readLine())!=null){
content.append(line).append("\n");
}
bufferedReader.close();
}catch (Exception e){
e.printStackTrace();
}
json_drug = content.toString();
return content.toString();
}
@Override
public void onBackPressed() {
Intent intent = new Intent(this,patient_mainPage.class);
startActivity(intent);
}
public void createDrugDialog(View view){
openDrugDialog();
}
private void openDrugDialog() {
drug_add_dialog drug_add_dialog = new drug_add_dialog();
drug_add_dialog.show(getSupportFragmentManager(),"ثبت داروی جدید");
}
}
Решение
После 3 дней стука в голову я мог узнать, что не так в моих кодах, если кто-то из вас По той же проблеме я создавал экземпляр Picasso в getview, поэтому каждый раз, когда пользователь прокручивал список для каждой строки, создавался экземпляр, который занимал много ресурсов и в некоторых случаях вызывал сбой из-за утечки памяти. поэтому я просто переместил конструктор Picasso над getView и просто вызвал его внутри getView:
Picasso builder = new Picasso.Builder(getContext()).build();
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View r = convertView;
ViewHolder viewHolder;
if (r == null) {
LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
r = layoutInflater.inflate(R.layout.row_layout_drugs, null, true);
viewHolder = new ViewHolder(r);
r.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) r.getTag();
}
drugs_json_data drugs_json_data = getItem(position);
viewHolder.txtDrugId.setText(drugs_json_data.getDrugId());
viewHolder.txtDrugName.setText(drugs_json_data.getDrugName());
viewHolder.txtDrugCategory.setText(drugs_json_data.getDrugCategory());
builder.load(drugs_json_data.getDrugImage()).memoryPolicy(MemoryPolicy.NO_STORE).placeholder(R.drawable.ic_launcher_foreground).into(viewHolder.imageView);
return r;
}
Остальное осталось прежним. Надеюсь, это поможет кому-то:)