Android ProgressDialog Progress Bar fare le cose nel giusto ordine

? FauxReal @ | Original: StackOverFlow

Ho quasi ottenuto questo, ma ho un piccolo problema nell'ordine delle cose andare fuori . In particolare, nel mio thread ( ) Io sono la creazione di una matrice che viene utilizzato da un Spinner . Il problema è la Spinner è tutto pronto e fatto praticamente prima del mio filo ( ) è finito, per cui si pone con una matrice null.

Come posso associare i filatori ArrayAdapter di una serie che viene caricata da un altro thread ?

Ho tagliato il codice fino a quello che penso sia necessario per capire il problema, ma solo fammi sapere se è necessario più . Il problema si verifica o meno RefreshData ( ) viene chiamato .

Sulla stessa linea, a volte voglio chiamare loadData ( ) dal menu . Subito dopo loadData ( ) se provo a sparare un brindisi nella riga successiva questo provoca un forceclose, che è anche a causa di come sto implementando ProgressDialog .

GRAZIE PER LO SGUARDO

public class CMSHome extends Activity { 

private static List<String> pmList = new ArrayList<String>();

// Instantiate helpers
PMListHelper plh = new PMListHelper();
ProjectObjectHelper poc = new ProjectObjectHelper();

// These objects hold lists and methods for dealing with them
private Employees employees;
private Projects projects;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    // Loads data from filesystem, or webservice if necessary
    loadData();

    // Capture spinner and associate pmList with it through ArrayAdapter
    spinner = (Spinner) findViewById(R.id.spinner);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                    this, android.R.layout.simple_spinner_item,
                    pmList);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

    //---the button is wired to an event handler---
    Button btn1 = (Button)findViewById(R.id.btnGetProjects);
    btn1.setOnClickListener(btnListAllProjectsListener);
    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}


private void loadData()
{
    final ProgressDialog pd = ProgressDialog.show(this,
            "Please wait", "Loading Data...", true, false);

    new Thread(new Runnable(){
        public void run(){
            employees = plh.deserializeEmployeeData();
            projects = poc.deserializeProjectData();

            // Check to see if data actually loaded, if not then refresh
            if ((employees == null) || (projects == null)) {
                refreshData();
            }

            // Load up pmList for spinner control
            pmList = employees.getPMList();

            pd.dismiss();
        }
    }).start();
}

private void refreshData()
{
    // Refresh data for Projects
    projects = poc.refreshData();
    poc.saveProjectData(mCtx, projects);

    // Refresh data for PMList          
    employees = plh.refreshData();
    plh.savePMData(mCtx, employees);
}
}

< ---- EDIT ----- > Ho provato a cambiare onCreate () per la seguente dopo Jims suggerimento . Non so se ho fatto questo diritto, ancora non funziona :

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mCtx = this;

    // Loads data from filesystem, or webservice if necessary
    // Would like to extend this to update if files are over x days old
    final ProgressDialog pd = ProgressDialog.show(this,
            "Please wait", "Loading Data...", true, false);

    new Thread(new Runnable(){
        public void run(){
            employees = plh.deserializeEmployeeData();
            projects = poc.deserializeProjectData();

            // Check to see if data actually loaded, if not then refresh
            if ((employees == null) || (projects == null)) {
                refreshData();
            }

            pd.dismiss();

            runOnUiThread(new Runnable() {
                public void run(){
                    // Load up pmList for spinner control
                    pmList = employees.getPMList();
                }
            });

        }
    }).start();

    spinner = (Spinner) findViewById(R.id.spinner);
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(
            this, android.R.layout.simple_spinner_item, pmList);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    spinner.setAdapter(adapter);

    //---the button is wired to an event handler---
    Button btn1 = (Button)findViewById(R.id.btnGetProjects);
    btn1.setOnClickListener(btnListAllProjectsListener);
    spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
}

Wow, questo ha preso per sempre per me trovare una soluzione, ma Im felice di aver finalmente ottenuto questo lavoro.

Aggiornamento del Spinner con un filo di fondo può essere realizzato utilizzando un gestore . Il gestore viene chiamato dopo il lavoro principale del filo è completata .

  mProgressDlg = ProgressDialog.show(this, "App_Name", "Loading data...", 
                                    true, false);
  new Thread(new Runnable(){
            public void run() {
                    /*Load Data, set pmList in my case*/
                    mProgressDlg.dismiss();
                    hRefresh.sendEmptyMessage(REFRESH);
            }
    }).start();



Handler hRefresh = new Handler(){

@Override
public void handleMessage(Message msg) {
   switch(msg.what){
     case REFRESH:
                 spinner = (Spinner) findViewById(R.id.spinner);
                 final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
                         mCtx, android.R.layout.simple_spinner_item, pmList);
                 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
                 spinner.setAdapter(adapter);
                 spinner.setOnItemSelectedListener(new MyOnItemSelectedListener());
            break;
   }
}
};

Ringraziamo bhatt4982 e la sua risposta su http://stackoverflow.com/questions/1458190/how-can-i-display-a-progress-at-start-up-application-in-android

Top 5 Risposta

1Jim Blackler @

Tutto il lavoro dopo loadData ( ) in onCreate ( ) deve essere fatto dopo il lavoro in run ( ) nel thread innescato in loadData ( ) è stata completata . Prova inlining loadData ( ), e l'aggiunta di questo lavoro di post -setup per un runOnUiThread ( ) dopo pd.dismiss ( ) .

2BJB @

Non so se hai mai risolto questo, ma questo funziona per me :

public class Start extends Activity {
private static final String TAG = "PriceList";

ArrayAdapter<ProductCategory> category_adapter;
ArrayAdapter<ProductGroup> group_adapter;

ArrayList<ProductCategory> categories;
ArrayList<ProductGroup> groups;

ArrayList<Price> prices;

Spinner group_spinner;
Spinner category_spinner;
ProgressDialog progressDialog;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    group_spinner = (Spinner) findViewById(R.id.group_spinner);
    category_spinner = (Spinner) findViewById(R.id.category_spinner);

    // product category spinner
    categories = new ArrayList<ProductCategory>();

    category_adapter = new CustomArrayAdapter<ProductCategory>(categories);
    category_adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

    // load category spinner from database
    loadCategory();     // adapter MUST be setup before this is called

    category_spinner.setAdapter(category_adapter);
    category_spinner.setOnItemSelectedListener(new OnItemSelectedListener () {


    ..... other stuff ...... 


private final Handler handler = new Handler() {
    @Override
    public void handleMessage(final Message msg) {
        Log.v(TAG, "worker thread done, setup adapter");

        switch (msg.what) {
        case Constants.CATEGORIES:
            category_adapter.notifyDataSetChanged();
            break;
        case Constants.GROUPS:
            group_adapter.notifyDataSetChanged();
            break;
        case Constants.PRICES:
            startActivity(new Intent(Start.this, ShowPrices.class));
            break;
        default:
        }
        // dismiss dialog
        progressDialog.dismiss();
    }
};

    // loadCategory() essentially the same....

private void loadGroup(final String cat) {
    Log.v(TAG, "loadGroup");

    progressDialog = new ProgressDialog(this);
    progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    progressDialog.setMessage("Retrieving Product Groups...");
    progressDialog.setMax(100);
    progressDialog.setProgress(0);
    progressDialog.show();

    new Thread() {

        @Override
        public void run() {

            int count = 100;
            int i = 0;

            SQLiteDatabase db = DbUtils.getStaticDb();

            Cursor c = db.rawQuery("select count(*) from productgroup where category = '"
                            + cat + "';", null);
            c.moveToFirst();
            if (!c.isAfterLast()) {
                count = c.getInt(0);
            }
            c.close();

            progressDialog.setMax(count);

            groups.clear();
            groups.add(new ProductGroup("-1", "--- Select ---"));

            StringBuilder sb = new StringBuilder("select _id,description from productgroup");
            sb.append(" where category = '");
            sb.append(cat);
            sb.append("' order by description;");
            Log.v(TAG, sb.toString());

            c = db.rawQuery(sb.toString(), null);
            c.moveToFirst();
            while (!c.isAfterLast()) {
                Log.v(TAG, c.getString(0));
                groups.add(new ProductGroup(c.getString(0), c.getString(1)));
                i++;
                if (i % 5 == 0) {
                    progressDialog.setProgress(i);
                }
                c.moveToNext();
            }
            c.close();

            // tell UI thread OK
            handler.sendEmptyMessage(Constants.GROUPS);
        }
    }.start();
}

    // custom ArrayAdapter allows us to have our own ArrayList<T>

class CustomArrayAdapter<T> extends ArrayAdapter<T> {

    CustomArrayAdapter(ArrayList<T> list) {
        super(Start.this, android.R.layout.simple_spinner_item, list);
    }

}
3WareNinja @

Vorrei anche suggerire di utilizzare https://github.com/commonsguy/cwac-task ha molto bello impl AsyncTaskEx, che è possibile utilizzare per fare lavori pesanti senza bloccare l'interfaccia utente .

Example class;

protected class DoHeavyWorkAsync extends AsyncTaskEx<Void, Integer, String> {
        private static final String TAG = "DoHeavyWorkAsync";

        @Override
        protected String doInBackground(Void... arg0) {

            // do heavy work here. e.g. loadDataFromSomewhere();
            YourActivity.this.runOnUiThread(new Runnable() {
                public void run() {
                    // you can do ui work on the main activity from here
                }
            });

            return null;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            Log.d(TAG, "onPreExecute()");
                    //e.g. display "loading..." 
        }
        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            Log.d(TAG, "onPostExecute()");
        }
    }

dalla vostra attività principale è possibile chiamare in questo modo ;

(new DoHeavyWorkAsync()).execute();