Я пробовал это некоторое время, и моя неопытность брала верх надо мной. Любые указатели или предложения о том, как мне следует подходить к проблеме, будут очень признательны.
У меня есть собственный ListView, каждый элемент которого содержит две строки. Один конкретный элемент в ListView меняет режим работы. Чего я пытаюсь добиться, так это:
- Щелкнув этот элемент ListView, откройте диалоговое окно, содержащее список, прикрепленный к переключателям.
- При выборе одного из элементов диалогового окна закройте диалоговое окно и измените одну из двух строк ListView в этом элементе, чтобы отразить этот выбор режима.
Мои вопросы таковы: как я могу обновить элементы ListView при нажатии кнопки диалога?
Я могу создать ListView и Dialog, но обновление ListView оказывается сложным. Начальные значения могут быть установлены, но не обновляются. Я знаю, что мне нужно вызвать .notifyDataSetChanged, но, поскольку я хотел бы, чтобы это произошло внутри onItemClick для диалогового окна, я получаю сообщение об ошибке: «Невозможно ссылаться на неконечную переменную внутри внутреннего класса, определенного в другом методе. ", и мои переменные не могут быть окончательными.
Что я пробовал:
- Уведомление об изменении данных непосредственно перед закрытием диалогового окна. Получил ошибку "неконечная переменная".
- Реализация настройки контроллера представления модели и попытка создать метод, который действует как «onVariableChangeListener», но я оставил эту идею, потому что она казалась немного не по теме, и я не совсем ее понимал.
- Создайте один метод для вызова диалогового окна и другой для обновления данных ListView. Проблема заключалась в том, что метод Update не ожидал нажатия элемента Dialog. Даже после изменения и повторного открытия диалогового окна ListView не обновляется.
- Создание метода, работающего аналогично onCreateView, который вызывается при каждом щелчке элемента. Он должен создать и раздуть новый ListView. Поскольку он вызывается в onItemClick, он не имеет ошибки «неконечная переменная», хотя мне потребовалось создать окончательные экземпляры параметров onCreateView. Я не уверен в последствиях, которые это имеет. Это верный подход?
Следующий код представляет собой смесь двух последних идей. Существуют методы для диалога и обновления отдельно, хотя обновление не ждет диалога, и параметры, идущие в метод обновления, являются окончательными.
Я надеюсь, что решение будет простым, но я считаю, что на работе есть несколько ошибок. Я знаю, что SO любит задавать вопросы, которые могут относиться к другим, кто может прочитать это позже, поэтому я прошу прощения, если это немного специфично для моего случая. Любая помощь приветствуется!
CalibrationFragment.java
public class CalibrationFragment extends Fragment{
private Context mContext;
private ArrayList<DataItem> data = new ArrayList<DataItem>(); // DataItem is a class that sets two strings
private ArrayList<DataItem> currentData = new ArrayList<DataItem>(); // Two records kept to identify changes
ListView myList;
int checkedItem1 = 0; // For the dialog boxes.
@Override
public void onCreate (Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mContext = getActivity(); // Get the context of the Activity and therefore the fragment
myList = new ListView (mContext); // Create a ListView
// Set initial values
calibrationData readData = new calibrationData(); // readData will contain all ListView values
// ... other items...
readData.setMode(checkedItem1, mContext); // Set to 0, 1 or 2 indicating different modes
// ... other items...
// Create elements to be added to the list
// ...
DataItem calibration4 = new DataItem(getResources().getString(R.string.mode_calibration), readData.getMode());
// readData.getMode() returns different strings depending on int input
// ...
// Add elements to the list
// ...
data.add(calibration4);
// ...
currentData = data; // Initialise both as the same
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the view
View rootView = inflater.inflate(R.layout.fragment_list, container, false);
myList=(ListView) rootView.findViewById(android.R.id.list);
// Create and set the customised adapter to take data (ArrayList<DataItem>) and format
// each element as defined in list_row.xml
CustomAdapter adapter = new CustomAdapter(mContext, R.layout.list_row, data);
myList.setAdapter(adapter);
// The above adapter is the one I need to notify
// For the sake of letting my code compile in onItemClick. Unsure if this causes further issues.
final LayoutInflater finalInflater = inflater;
final ViewGroup finalContainer = container;
final Bundle finalSavedInstanceState = savedInstanceState;
// CustomAdapter adapter cannot be used in setOnItemClickListener because it is non-final
myList.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parentAdapter, View view, int position, long id)
{
switch((int)id){
// [Different cases here]
case 3: // Clicks of Mode item
// Creates Dialog
showDialog((int)id, checkedItem1);
// updateData executes as Dialog is generated, not clicked or closed. Do not want this.
updateData(finalInflater, finalContainer, finalSavedInstanceState);
break;
// [Rest of the cases and default statement here]
}
}
});
return rootView; // onCreateView must return a View variable if displaying a UI.
}
public void showDialog(int id, int checkedItem)
{
// In case I want to have other dialogs later, ensure this is for Mode selection.
if(id == 3){
final CharSequence[] modeItems = {
"Mode 1", "Mode 2", "Mode 3"
}; // For Dialog
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
builder.setTitle(getResources().getString(R.string.mode_calibration));
builder.setSingleChoiceItems(modeItems, checkedItem, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int item) {
checkedItem1 = item; // Change checkedItem1 to the index selected in the dialog
calibrationData readData = new calibrationData();
readData.setMode(checkedItem1, mContext); // Set Mode depending on checkedItem
// Create DataItem representing new mode
DataItem newMode = new DataItem(getResources().getString(R.string.mode_calibration), readData.getMode());
currentData.set(3, newMode); // Set new mode into currentData.
// Eventual comparison with var 'data' will indicate a change
dialog.dismiss();
}
});
AlertDialog alert = builder.create();
alert.show();
}
public View updateData(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
// Inflate the new view
View rootView = inflater.inflate(R.layout.fragment_list, container, false);
myList=(ListView) rootView.findViewById(android.R.id.list);
// Create and set the customised adapter to take data (ArrayList<DataItem>) and format
// each element as defined in list_row.xml
CustomAdapter adapter = new CustomAdapter(mContext, R.layout.list_row, data);
myList.setAdapter(adapter);
// As this is only called in onClick, I can work with data assuming something has changed and been clicked.
int i = 0;
// Compare each element inside data and currentData.
for(i = 0; i < data.size(); i++){
if(data.get(i) != currentData.get(i)) data = currentData;
if(i==5) Toast.makeText(mContext, "Iterating to end", Toast.LENGTH_SHORT).show(); // debug purposes
}
adapter.notifyDataSetChanged(); // Update list
return rootView;
}