Question

In my class there are various AutoCompleteTextView, and all of them have the same ArrayAdapter as hints. This text views are used to sent data to a php page through an AsyncTask, and in his doInBackground method I check that the value inserted is one of the value contained into the adapter(I don't want to accept any other value). For this check I simply do:

if(fermate.getPosition(fermata) < 0){
   return "lineaNonPresente";  // It is returned to onPostExecute
}

In this snap of code, fermate is the ArrayAdapter, and fermata is the string that should not be found into the adapter. If otherwise it is found, I return a String ending doInBackground.

What is the problem? The problem is the object fermate. When I check the ArrayAdapter does not contain no more the original values, but just some of them. I saw it by watching this variable during the debug. Into fermate there is an array mObjets that contains

[Via Roma - Cod: 2, San Rocco - Cod: 4, null, null, null, null, null, null, null, null, null, null]

and an array mOriginalValues that contains

[Piazza Torino - Cod: 1, Via Roma - Cod: 2, Corso Nizza - Cod: 3, San Rocco - Cod: 4, Crocetta - Cod: 5, Provincia - Cod: 6, Municipio - Cod: 7, Piazzale Serenella - Cod: 9, FermataLocale - Cod: 16, Mi Serve - Cod: 17]

(all the element that should be into fermate).

When I create the adapter, mObject contains [Piazza Torino - Cod: 1, Via Roma - Cod: 2, Corso Nizza - Cod: 3, San Rocco - Cod: 4, Crocetta - Cod: 5, Provincia - Cod: 6, Municipio - Cod: 7, Piazzale Serenella - Cod: 9, FermataLocale - Cod: 16, Mi Serve - Cod: 17] and mOriginalValues is null.

So my questions are two:

  • Why in the AsyncTask the values contained into the ArrayAdapter change?
  • How can I make so that the method getPosition() searches into mOriginalValues? Or doing so that the array mObjects will not be affected from uncontrolled changes?

I let the code of the whole class here to help.

package com.example.app.Fragment;

imports [...]

public class FragmentAggiungiLinea extends Fragment {

private Context context;
private LayoutInflater li;
private Button btnNuovaFermata;
private Button btnEliminaFermata;
private Button btnConfermaLinea;
private AutoCompleteTextView primaFermata;
private EditText edtNomeLinea;
private EditText edtCodiceLinea;
private LinearLayout layoutBase;
private ArrayAdapter<String> fermate;

@SuppressWarnings("unused")
private static final String TAG = FragmentAggiungiLinea.class.getSimpleName();

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_aggiungi_linea, container, false); }


@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);

    context = getActivity();
    li = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    btnEliminaFermata = (Button) getView().findViewById(R.id.btnEliminaFermata);
    btnNuovaFermata = (Button) getView().findViewById(R.id.btnNuovaFermata);
    btnConfermaLinea = (Button) getView().findViewById(R.id.btnConfermaLinea);
    layoutBase = (LinearLayout) getView().findViewById(R.id.layoutBase);
    primaFermata = (AutoCompleteTextView) getView().findViewById(R.id.edtPrimaFermata);
    edtNomeLinea = (EditText) getView().findViewById(R.id.edtNomeLinea);
    edtCodiceLinea = (EditText) getView().findViewById(R.id.edtCodiceLinea);
    fermate = new ArrayAdapter<String>(context,android.R.layout.simple_dropdown_item_1line);
    creaAdapter();
    primaFermata.setAdapter(fermate);

    btnNuovaFermata.setOnClickListener(new OnClickListener() {          
        public void onClick(View v) {
                if(!((EditText)((LinearLayout) layoutBase.getChildAt(layoutBase.getChildCount() - 1)).getChildAt(1)).getText().toString().matches("")){
                    LinearLayout nuovoLayout = (LinearLayout) li.inflate(R.layout.nuova_fermata_intermedia, null);


                    // I get the new EditText and I put the adapter.
                    AutoCompleteTextView nuovaFermata = (AutoCompleteTextView) nuovoLayout.getChildAt(1);                       
                    nuovaFermata.setAdapter(fermate);               
                    layoutBase.addView(nuovoLayout);    


                    btnEliminaFermata.setEnabled(true);
                }else{
                    Toast.makeText(context, "Completare prima l'ultima fermata", Toast.LENGTH_SHORT).show();
                }
        }
    });

    btnEliminaFermata.setEnabled(false);
    btnEliminaFermata.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            layoutBase.removeViewAt(layoutBase.getChildCount() - 1);
            if(layoutBase.getChildCount() == 1) btnEliminaFermata.setEnabled(false);
        }
    });

    btnConfermaLinea.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            if(!edtCodiceLinea.getText().toString().matches(""))
                if(!edtNomeLinea.getText().toString().matches(""))
                    new UploadLinea().execute();

        }
    });

}

private void creaAdapter(){
    // I create an adapter with the stops.
    fermate.clear();

    // I get the local database.
    DatabaseLocale db = new DatabaseLocale(context);
    SQLiteDatabase dbLeggibile = db.getReadableDatabase();

    String[] colonne = {DatabaseLocale.getTagCodiceFermata(), DatabaseLocale.getTagNomeFermata()};
    String tabella = DatabaseLocale.getTableNameFermata();
    Cursor cursore = dbLeggibile.query(tabella, colonne, null, null, null, null, null);
    while(cursore.moveToNext()){
        fermate.add(cursore.getString(1) + " - Cod: " + cursore.getString(0));
    }

    cursore.close();
    db.close();
}

class UploadLinea extends AsyncTask<Void, Void, String>{
    private ProgressDialog pDialog;
    @SuppressWarnings("unused")
    private final String TAG = UploadLinea.class.getSimpleName();
    private String NUOVA_LINEA;
    List<NameValuePair> params = null;
    JSONObject json = null;
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(context);
        pDialog.setMessage("Caricamento linea...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(true);
        pDialog.show();
        NUOVA_LINEA = GlobalClass.getDominio() + "Upload/caricaLinea.php";
    }

    protected String doInBackground(Void... voids) {

        String valoreRitornato = null;
        JSONParser jsonParser = new JSONParser();
        try {
            params = new ArrayList<NameValuePair>();
            params.add(new BasicNameValuePair("NomeLinea", edtNomeLinea.getText().toString()));
            params.add(new BasicNameValuePair("CodLinea", edtCodiceLinea.getText().toString()));
            int indice = 0;
            while(indice < layoutBase.getChildCount()){
                LinearLayout layoutFermata = (LinearLayout) layoutBase.getChildAt(indice);
                String fermata = ((AutoCompleteTextView) layoutFermata.getChildAt(1)).getText().toString();
                if(fermate.getPosition(fermata) < 0){  // HERE THERE IS THE PIECE OF CODE
                    return "lineaNonPresente"; 
                }
                if(trovatoInArrayList(fermata.split(" - Cod: ")[1])){
                    return "giaPresente"; 
                }
                params.add(new BasicNameValuePair("Fermate[]", fermata.split(" - Cod: ")[1]));
                indice++;
            }

            // Request to the .php page.
            json = jsonParser.makeHttpRequest(
                    NUOVA_LINEA, "POST", params);

            valoreRitornato = json.getString(GlobalClass.getTagMessage());
        } catch (JSONException e) {
            Log.e(TAG, "Error " + e.toString());
        }

        return valoreRitornato;
    }

    @Override
    protected void onPostExecute(String valoreRitornato) {
        super.onPostExecute(valoreRitornato);
        pDialog.dismiss();            

        if(valoreRitornato == "giaPresente"){
            valoreRitornato = "Ogni fermata può essere inserita una volta soltanto.";
        } else if(valoreRitornato == "lineaNonPresente"){
            valoreRitornato = "Le linee devono avere uno dei valori suggeriti.";
        }else{
            try {

                if(json.getInt(GlobalClass.getTagSuccess()) != 0){
                    DatabaseLocale db = new DatabaseLocale(context);
                    SQLiteDatabase dbScrivibile = db.getWritableDatabase();

                    ContentValues valori = new ContentValues();
                    valori.put(DatabaseLocale.getTagCodiceLinea(), edtCodiceLinea.getText().toString());
                    valori.put(DatabaseLocale.getTagNomeLinea(), edtNomeLinea.getText().toString());
                    valori.put(DatabaseLocale.getTagCodiceCapolinea(), 
                            ((AutoCompleteTextView)((LinearLayout) layoutBase.getChildAt(0)).getChildAt(1)).getText().toString().split(" - Cod: ")[1]);
                    dbScrivibile.insert(DatabaseLocale.getTableNameLinea(), null, valori);

                    for (int i = 0; i < params.size(); i++) {
                        BasicNameValuePair valore = ((BasicNameValuePair) params.get(i));
                        if(valore.getName() == "Fermate[]" && i != (params.size() - 1)){                            
                            valori = new ContentValues();
                            valori.put(DatabaseLocale.getTagCodiceLinea(), edtCodiceLinea.getText().toString());
                            valori.put(DatabaseLocale.getTagCodiceFermata(), valore.getValue());
                            valori.put(DatabaseLocale.getTagSuccessiva(), ((BasicNameValuePair) params.get(i + 1)).getValue());
                        }else if(i == (params.size() - 1)){                         
                            valori = new ContentValues();
                            valori.put(DatabaseLocale.getTagCodiceLinea(), edtCodiceLinea.getText().toString());
                            valori.put(DatabaseLocale.getTagCodiceFermata(), valore.getValue());
                            valori.put(DatabaseLocale.getTagSuccessiva(), 0);
                        }
                        dbScrivibile.insert(DatabaseLocale.getTableNameTratta(), null, valori);
                    }

                    dbScrivibile.close();
                    db.close();
                }
            } catch (JSONException e) {
                Log.e(TAG, "Error " + e.toString());
            }

            while(layoutBase.getChildCount() > 1) layoutBase.removeViewAt(layoutBase.getChildCount() - 1);
            primaFermata.setText("");
            edtCodiceLinea.setText("");
            edtNomeLinea.setText("");
        }

        Toast.makeText(context, valoreRitornato, Toast.LENGTH_LONG).show();
        Log.d(TAG, valoreRitornato);

    }

    private boolean trovatoInArrayList(String s){
        for (NameValuePair elemento : params) {
            if(elemento.getValue() == s) return true;
        }
        return false;
    }
}

}

UPDATE: I tryed to do the checks into the onClickListener before to call AsyncTask.execute(), and I get the same problem. The new part of code is this:

btnConfermaLinea.setOnClickListener(new OnClickListener() {

        public void onClick(View v) {
            if(!edtCodiceLinea.getText().toString().matches(""))
                if(!edtNomeLinea.getText().toString().matches("")){
                    // Creo qui i parametri per risolvere il problema:
                    // http://stackoverflow.com/questions/23399793/arrayadapter-getposition-item-not-found-it-is-in-moriginalvalues
                    // (non ho ancora ricevuto risposte).
                    params = new ArrayList<NameValuePair>();
                    params.add(new BasicNameValuePair("NomeLinea", edtNomeLinea.getText().toString()));
                    params.add(new BasicNameValuePair("CodLinea", edtCodiceLinea.getText().toString()));
                    int indice;
                    for(indice = 0; indice < layoutBase.getChildCount(); indice++){
                        LinearLayout layoutFermata = (LinearLayout) layoutBase.getChildAt(indice);
                        String fermata = ((AutoCompleteTextView) layoutFermata.getChildAt(1)).getText().toString();
                        if(trovatoInArrayList(fermata.split(" - Cod: ")[1])){
                            Toast.makeText(context, "Ogni fermata può essere inserita una volta soltanto.", Toast.LENGTH_LONG).show();
                            break;
                        }
                        if(fermate.getPosition(fermata) < 0){
                            Toast.makeText(context, "Le linee devono avere uno dei valori suggeriti.", Toast.LENGTH_LONG).show();
                            break;
                        }
                        params.add(new BasicNameValuePair("Fermate[]", fermata.split(" - Cod: ")[1]));
                    }if(indice == layoutBase.getChildCount())
                        new UploadLinea().execute();

                }


        }
    });
Was it helpful?

Solution

Why in the AsyncTask the values contained into the ArrayAdapter change?

Because you filter the adapter(through the AutoCompleteTextView widget) which makes it have a subset of the data.

How can I make so that the method getPosition() searches into mOriginalValues?

You don't. That field is made private so you can't normally access it(and you shouldn't anyway).

Or doing so that the array mObjects will not be affected from uncontrolled changes?

You're approaching this the wrong way. The Arrayadapter has two lists of data to be able to handle the filtering: one list containing the initially passed set of data(this is required so you can bring the adapter to the initial state after a filter reset) and the current list of data on which the adapter is currently based(so any interaction with the adapter will take this list in consideration). You have two options:

  • retrieve the data(what you do in the creaAdapter() method) into a list(and not just add the items directly to the adapter) and keep a reference to that list in your fragment(remember to update it if it changes). When you want to use the value entered check that item against the list reference that you stored, basically what the adapter does under the hood:

    if(mAdapterDataListReference.indexOf(fermata) < 0){  // HERE THERE IS THE PIECE OF CODE
       return "lineaNonPresente"; 
    }
    
  • extend the ArrayAdapter to add your own list reference. This reference will be initialized in the adapter's constructor, you'll also need to override the other methods that allow adding/deleting data like add(), addAll(), clear(). Then you also override the getItemPosition() to look for the item in your own added data list reference. I wouldn't choose this because if the ArrayAdapteruses the getItemPosition() in its implementation you could mess things up

Also, and all of them have the same ArrayAdapter as hints., I hope you're not using the same adapter instance(a single instance) with all the AutoCompleteTextView widgets that you have.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top