ListView не обновляется с notifydatasetchanged - PullRequest
0 голосов
/ 29 августа 2018

У меня есть база данных MySQL из двух столбцов, отображаемых в Android ListView. Я использую Retrofit 1.9 для получения данных из MySQL. Адаптер для ListView - это BaseAdapter, а у меня нет DatabaseHelper класса. Когда я добавляю данные в ListView со своего мобильного телефона, они не обновляют ListView. Я должен закрыть и перезапустить приложение. Я пытаюсь обновить с listViewAdapter.notifyDataSetChanged();.

Это фрагмент со списком:

public class rightFragment extends Fragment {

String BASE_URL = "http://awebsite.com";

View view;
ListView listView;
ListViewAdapter listViewAdapter;

Button buttondisplay;
Button buttonadd;
EditText new_id;
EditText newWordFra;
EditText newWordDeu;

ArrayList<String> id = new ArrayList<>();
ArrayList<String> fra = new ArrayList<>();
ArrayList<String> deu = new ArrayList<>();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    view = inflater.inflate(com.example.geeko.Deu.R.layout.fragment_right, container, false);

    listView = (ListView) view.findViewById(com.example.geeko.Deu.R.id.listView); //<<<< ADDED NOTE use your id
    listViewAdapter = new ListViewAdapter(getActivity(), id, fra, deu);

    displayData();

    buttondisplay = (Button) view.findViewById(com.example.geeko.Deu.R.id.buttondisplay);
    buttonadd = (Button) view.findViewById(com.example.geeko.Deu.R.id.buttonadd);
    buttondelete = (Button) view.findViewById(com.example.geeko.Deu.R.id.newID);
    newWordFra = (EditText) view.findViewById(com.example.geeko.Deu.R.id.newWordFra);
    newWordDeu = (EditText) view.findViewById(com.example.geeko.Deu.R.id.newWordDeu);

    buttonadd.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            //Toast.makeText(MainActivity.this , "button add", Toast.LENGTH_LONG).show();
            insert_data();
           listViewAdapter.notifyDataSetChanged();

        }
    });

    buttondisplay.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (buttondisplay.getText().toString().contains("Show")) {
                listView.setAdapter(listViewAdapter);
                buttondisplay.setText("Hide");
            } else {
                listView.setAdapter(null);
                buttondisplay.setText("Show");
            }
        }
    });


    listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long ids) {

            new_id.setText(id.get(position));
            newWordFra.setText(fra.get(position));
            newWordDeu.setText(deu.get(position));

        }
    });

    return view;

}

public void insert_data() {

    RestAdapter adapter = new RestAdapter.Builder()
            .setEndpoint(BASE_URL) //Setting the Root URL
            .build();

    AppConfig.insert api = adapter.create(AppConfig.insert.class);

    api.insertData(
            newWordFra.getText().toString(),
            newWordDeu.getText().toString(),
            new Callback<Response>() {
                @Override
                public void success(Response result, Response response) {

                    try {

                        BufferedReader reader = new BufferedReader(new InputStreamReader(result.getBody().in()));
                        String resp;
                        resp = reader.readLine();
                        Log.d("success", "" + resp);

                        JSONObject jObj = new JSONObject(resp);
                        int success = jObj.getInt("success");

                        if(success == 1){
                            Toast.makeText(getActivity(), "Successfully inserted", Toast.LENGTH_SHORT).show();
                        } else{
                            Toast.makeText(getActivity(), "Insertion Failed", Toast.LENGTH_SHORT).show();
                        }

                    } catch (IOException e) {
                        Log.d("Exception", e.toString());
                    } catch (JSONException e) {
                        Log.d("JsonException", e.toString());
                    }
                }

                @Override
                public void failure(RetrofitError error) {
                    Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
                }
            }
    );
}

public void displayData() {

    RestAdapter adapter = new RestAdapter.Builder()
            .setEndpoint(BASE_URL) //Setting the Root URL
            .build();

    AppConfig.read api = adapter.create(AppConfig.read.class);

    api.readData(new Callback<JsonElement>() {
                     @Override
                     public void success(JsonElement result, Response response) {

                         String myResponse = result.toString();
                         Log.d("response", "" + myResponse);

                         try {
                             JSONObject jObj = new JSONObject(myResponse);

                             int success = jObj.getInt("success");

                             if (success == 1) {

                                 JSONArray jsonArray = jObj.getJSONArray("details");
                                 for (int i = 0; i < jsonArray.length(); i++) {

                                     JSONObject jo = jsonArray.getJSONObject(i);

                                     id.add(jo.getString("id"));
                                     fra.add(jo.getString("fra"));
                                     deu.add(jo.getString("deu"));


                                 }

                                 listView.setAdapter(listViewAdapter);


                             } else {
                                 Toast.makeText(getActivity(), "No Details Found", Toast.LENGTH_SHORT).show();
                             }
                         } catch (JSONException e) {
                             Log.d("exception", e.toString());
                         }
                     }

                     @Override
                     public void failure(RetrofitError error) {
                         Log.d("Failure", error.toString());
                         Toast.makeText(getActivity(), error.toString(), Toast.LENGTH_LONG).show();
                     }
                 }
    );
  }

}

Это класс listViewAdpater:

public class ListViewAdapter extends BaseAdapter {

private final Context context;
private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> fra = new ArrayList<String>();
private ArrayList<String> deu = new ArrayList<String>();
LayoutInflater layoutInflater;

public ListViewAdapter(Context ctx, ArrayList<String> id, ArrayList<String> fra, ArrayList<String> deu) {

    this.context = ctx;
    this.id = id;
    this.fra = fra;
    this.deu = deu;

}

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

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

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

@SuppressLint("ViewHolder")
@Override
public View getView(final int position, View view, ViewGroup parent) {

    final Holder holder;
    if (view == null) {
        layoutInflater = (LayoutInflater) context.getSystemService
                (Context.LAYOUT_INFLATER_SERVICE);

        view = layoutInflater.inflate(R.layout.list_item, null);
        holder = new Holder();
        holder.txt_fra = (TextView) view.findViewById(R.id.fra);
        holder.txt_deu = (TextView) view.findViewById(R.id.deu);
        view.setTag(holder);
    } else {

        holder = (Holder) view.getTag();
    }

        holder.txt_fra.setText(fra.get(position));
        holder.txt_deu.setText(deu.get(position));


        return view;
    }

    static class Holder {
        TextView txt_fra, txt_deu;
    }

}

Должен ли я создать метод для обновления моего ListView?

Ответы [ 3 ]

0 голосов
/ 29 августа 2018
buttonadd.setOnClickListener(new View.OnClickListener() {
        ...
        insert_data();
       listViewAdapter.notifyDataSetChanged();

    }
});

В вашем onClickListener вы звоните insert_data(), затем следует listViewAdapter.notifyDataSetChanged()

insert_data() метод отправляет сетевой запрос на получение данных для заполнения списка. НО, вы звоните notifyDataSetChanged ДО завершения сетевого запроса. Вот почему listView пусто и останется пустым. Вам нужно подождать ПОСЛЕ сетевого запроса и ПОСЛЕ того, как вы набрали в ArrayList данные для вызова notifyDataSetChanged. Как мы узнаем, что сетевой запрос выполнен? Просто в конце обратного вызова (который вы реализовали):

new Callback<Response>() {
            @Override
            public void success(Response result, Response response) {...

В конце метода success вы вызываете метод listViewAdapter.notifyDataSetChanged().

Надеюсь, это имеет смысл! Попробуйте и дайте нам знать, что происходит

0 голосов
/ 30 августа 2018

Я нашел решение. Я добавил getActivity.recreate(); в методе insert_data .

public void success(Response result, Response response) {

                    try {

                        BufferedReader reader = new BufferedReader
                                (new InputStreamReader(result.getBody().in()));
                        String resp;
                        resp = reader.readLine();
                        Log.d("success", "" + resp);

                        JSONObject jObj = new JSONObject(resp);
                        int success = jObj.getInt("success");

                        if(success == 1){
                            Toast.makeText(getActivity(), "Successfully inserted",
                                    Toast.LENGTH_SHORT).show();
                            getActivity().recreate();

                        } else{
                            Toast.makeText(getActivity(), "Insertion Failed",
                                    Toast.LENGTH_SHORT).show();
                        }

                    } catch (IOException e) {
                        Log.d("Exception", e.toString());
                    } catch (JSONException e) {
                        Log.d("JsonException", e.toString());
                    }


                }

Я не уверен, что это лучшее решение, но оно работает.

0 голосов
/ 29 августа 2018

Прежде всего я бы предложил удалить ненужную инициализацию ваших переменных внутри Адаптера:

private ArrayList<String> id = new ArrayList<String>();
private ArrayList<String> fra = new ArrayList<String>();
private ArrayList<String> deu = new ArrayList<String>();

Назначая указатель из вашего фрагмента, вы уже назначите инициализированный ArrayList. Вы хотите, чтобы оба указателя указывали на один и тот же объект ArrayList, поэтому изменения применяются к обоим.

Видимо, данные, хранящиеся в адаптере, не обновляются правильно. Я бы посоветовал отладить ваше приложение - установить точку останова, чтобы вы могли видеть данные, которые адаптер сохраняет после обновления.

Идея написания метода для обновлений уже реализована с notifyDataSetChanged(). Просто переопределите метод в вашем адаптере и внесите возможные изменения перед вызовом super.notifyDataSetChanged().

Если у вас все получится с этими изменениями, сообщите нам.

...