android Async — диалоговое сообщение об обновлении в цикле

#java #android #asynchronous #dialog

#java #Android #асинхронный #диалоговое окно

Вопрос:

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


Пожалуйста, подождите… Графики загружаются…

0% завершено

Я выяснил, как получить процент от каждой итерации цикла, мне сложно обновить диалоговое окно до правильного процента. Заранее спасибо!!!!

// мой объект xml textview

   <TextView
    android:id="@ id/percentloaded"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="The graphs are loading...n0% Completed"
     android:layout_gravity="right"
     android:visibility="invisible"
      android:textColor="#FFFFFF"  />
 

// как я вызываю асинхронность внутри моей функции создания

  new MyAsync().execute();
 

//мой onCreate()

     protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.activity_network_showcharts);
    setRequestedOrientation (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 
    // fun little snippet that prevents users from taking screenshots
    // on ICS  devices :-)
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE,
                             WindowManager.LayoutParams.FLAG_SECURE);
    //Toast.makeText(NetworkAllInformation_ShowChart.this, "Please wait for graphs to finish loading", Toast.LENGTH_SHORT).show();

    progressDialog = new ProgressDialog(NetworkAllInformation_ShowChart.this);
   cycleDate = (TextView) findViewById(R.id.CycleDateAnswer);
    cycleDay = (TextView) findViewById(R.id.CycleDayAnswer);
    cycleDailyUsage = (TextView) findViewById(R.id.CycleUsageAnswer);
    cycleOverallUsage = (TextView) findViewById(R.id.TotalUsageAnswer);
    percentLoaded = (TextView) findViewById(R.id.percentloaded);


    stringofZero = "0";

    plot = (XYPlot) findViewById(R.id.mySimpleXYPlot);

    alertDialogBuilder = new AlertDialog.Builder(this);

     final Calendar calendar = Calendar.getInstance();


     year = calendar.get(Calendar.YEAR);
     month = calendar.get(Calendar.MONTH);
     day = calendar.get(Calendar.DAY_OF_MONTH);  

    currentDate = (month 1)  "-"  day  "-"  year;   


     theNumberOfDaysToCompare = day;

    intObj = new Integer(theNumberOfDaysToCompare); 

    intNumberOfMaxGBsAccepted = 0;
    numObj = (Number)intObj;  

     series1Numbers = new Number[(Integer) numObj];
     series2Numbers = new Number[(Integer) numObj];
     series3Numbers = new Number[(Integer) numObj];

     handler = new Handler();


    ParseQuery<ParseObject> query0 = ParseQuery.getQuery("ClientCompanyInfo");
    query0.whereEqualTo("SiteID", ShowSatellitesActivity.IDchosen);
    query0.addAscendingOrder("SiteID");
    query0.setLimit(1000);
    query0.selectKeys(Arrays.asList("UsagePlan"));



         List<ParseObject> results0 = null;
            try {
                results0 = query0.find();
            } catch (ParseException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }


             System.out.println("query0 size: " results0.size());
             for (ParseObject data : results0) {
                  // This does not require a network access.

                Integer.parseInt(data.getString("UsagePlan"));
                System.out.println("the usage plan is: " Integer.parseInt(data.getString("UsagePlan")) );

                if(Integer.parseInt(data.getString("UsagePlan")) >=1 )
                {
                    System.out.println("The usage plan is a set number");
                    intNumberOfMaxGBsAccepted = Integer.parseInt(data.getString("UsagePlan"));

                } //ends if

             }//ends for loop 



            new MyAsync().execute();



    sum = 0;



} //ends on create
 

// моя асинхронная задача

 private static class MyAsync extends AsyncTask <Void, Integer, String> {

      @Override
      protected void onPreExecute() {

       super.onPreExecute();

        // set title
        alertDialogBuilder.setTitle("Please wait...");

        alertDialogBuilder.setCancelable(false);
        // set dialog message
        alertDialogBuilder.setMessage(percentLoaded.getText());

        // create alert dialog
        alertDialog = alertDialogBuilder.create();

        // show it
        alertDialog.show();



      }


      protected static void onProgressUpdate(Integer progress) {


              alertDialog.setMessage("The graphs are loading...n" progress[0] "% Completed");
        alertDialog.dismiss();
            System.out.println("onProgressUpdate: " progress[0]);


         }

        protected void onPostExecute(String result) {

          System.out.println("onPostExecute: " result);

          alertDialog.setMessage("The graphs are loading...n" result "% Completed");

        }





    @Override
    protected String doInBackground(Void... params) {
        // TODO Auto-generated method stub



                incrementor = 0;
                for ( int i = 0; i<day; i  ){ 

                     //get information about the user
                     ParseQuery<ParseObject> query = ParseQuery.getQuery("UsageCalculator");
                     query.whereEqualTo("SiteID", ShowSatellitesActivity.IDchosen);
                     query.addAscendingOrder("SiteID");
                     query.setLimit(1000);
                     query.getFirstInBackground(new GetCallback<ParseObject>() {



                            public void done(ParseObject dailyUsage, ParseException e) {

                                if (e == null) {

                                    dayString = (1 incrementor);
                                     System.out.println("Day number: " Integer.toString(dayString)); 

                                     getThePercent =  Integer.toString((int) ((100 / (float) day) * dayString));
                                        System.out.println(getThePercent);


                                        Integer percentInt = Integer.valueOf((100 /day) * dayString);

                                        try{

                                    publishProgress(percentInt);
                                    Thread.sleep(1000);
                                        } catch(Exception e1){
                                            e1.printStackTrace();
                                        }


                                     //start
                                 ParseQuery<ParseObject> query2 = ParseQuery.getQuery("UsageCalculator");
                                 query2.whereEqualTo("monthString", String.valueOf(month 1)); //current month
                                 query2.whereEqualTo("SiteID", dailyUsage.getString("SiteID")); //the selected ID
                                 query2.whereEqualTo("yearString", String.valueOf(year)); //current year
                                 query2.whereEqualTo("dayString", Integer.toString(dayString)); //incremented through to have every day
                                 query2.addAscendingOrder("SiteID");
                                 query2.setLimit(1000);
                                 query2.selectKeys(Arrays.asList("dataUsedString", "usageDate")); //take the information out of the date and usage columns
                                 List<ParseObject> results = null;

                                try {
                                    results = query2.find();

                                } catch (ParseException e1) {
                                    // TODO Auto-generated catch block
                                    e1.printStackTrace();
                                }


                                 System.out.println("query8 size: " results.size());
                                 for (ParseObject data : results) {
                                      // This does not require a network access.

                                      myArray.add(data.getString("dataUsedString"));
                                 }

                                 //the last day reached
                                    if(myArray.size() == day-1){
                                        alertDialog.dismiss();
                                        plot.clear(); //erase the old plot
                                        updateGraphValues(); //get values of graph
                                        updateGraphBackground(); //set the values to the graph
                                        plot.redraw(); //redraw the plot with the correct values
                                    }
                               incrementor  ;

                                } //if the exception handler is null



                                else {
                                    Log.d("showChart", "Error: "   e.getMessage()); //if their is an exception
                                }

                            } //ends the done




                        }); //ends the query

                        } //ends the for loop








        return "";
        }



     }
 

// другие вызовы функций

     private static void updateGraphValues() {

      for (int i = 0; i<myArray.size(); i  ){

            usageValue = Double.parseDouble(myArray.get(i));

            //daily usage array
            series2Numbers[i] = usageValue;
            //total usage sumation array
            series1Numbers[i] = (usageValue increasingSum);
            //the max value 
            series3Numbers[i] = intNumberOfMaxGBsAccepted;
            vector.add((double) i);
            vector.add(Math.sin(i));

            //keeping a running sum
            if(usageValue!=0) { increasingSum= increasingSum usageValue; }
        }

        increasingSum = 0;

} // ends updating the graph value function

private static void updateGraphBackground() {

    // Turn the above arrays into XYSeries':
    series1 = new SimpleXYSeries(
            Arrays.asList(series1Numbers),          // SimpleXYSeries takes a List so turn our array into a List
            SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, // Y_VALS_ONLY means use the element index as the x value
            "Total");                             // Set the display title of the series

    // same as above
   series2 = new SimpleXYSeries(Arrays.asList(series2Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Daily");
   series3 = new SimpleXYSeries(Arrays.asList(series3Numbers), SimpleXYSeries.ArrayFormat.Y_VALS_ONLY, "Max");


    series1Format = new LineAndPointFormatter(Color.rgb(51, 51, 255), 0, Color.rgb(51, 153, 255), null);


    series1Format.getFillPaint().setStrokeJoin(Paint.Join.ROUND);
    series1Format.getFillPaint().setStrokeCap(Paint.Cap.ROUND);  
    series1Format.getFillPaint().setPathEffect(new CornerPathEffect(10) );
    series1Format.getFillPaint().setAntiAlias(true); 
    series1Format.getFillPaint().setStrokeWidth(8);


    // same as above:
    //daily green
    series2Format = new LineAndPointFormatter(Color.rgb(51, 255, 153), 0, Color.rgb(153, 255, 204), null);

    series2Format.getFillPaint().setStrokeJoin(Paint.Join.ROUND);
    series2Format.getFillPaint().setStrokeCap(Paint.Cap.ROUND);  
    series2Format.getFillPaint().setPathEffect(new CornerPathEffect(10) );
    series2Format.getFillPaint().setAntiAlias(true); 
    series2Format.getFillPaint().setStrokeWidth(8);

    series3Format = new LineAndPointFormatter(Color.rgb(255, 51, 51), 0, 0, null);

    series3Format.getFillPaint().setStrokeJoin(Paint.Join.ROUND);
    series3Format.getFillPaint().setStrokeCap(Paint.Cap.ROUND);  
    series3Format.getFillPaint().setPathEffect(new CornerPathEffect(10) );
    series3Format.getFillPaint().setAntiAlias(true); 
    series3Format.getFillPaint().setStrokeWidth(8);


    // add a new series' to the xyplot:
    plot.addSeries(series1, series1Format); //this one has to be first to that the domain and range can be found for this series
    plot.addSeries(series2, series2Format);
    plot.addSeries(series3, series3Format);

    // reduce the number of range labels
    plot.setTicksPerRangeLabel(1);
    plot.getGraphWidget().setDomainLabelOrientation(45);

    plot.calculateMinMaxVals();
    minXy=new PointF(plot.getCalculatedMinX().floatValue(),plot.getCalculatedMinY().floatValue());
    maxXY=new PointF(plot.getCalculatedMaxX().floatValue(),plot.getCalculatedMaxY().floatValue());

   // plot.setClickable(true);

    //NOTE about XYPlotZoomPan: when an OnTouchListener is set, zooming is disabled. Subclass to avoid it.
    plot.setOnTouchListener(new View.OnTouchListener(){

        public boolean onTouch(View v, MotionEvent me) {


            //the begin of finding a point touched, then drawing two lines, and labeling the lines
            touchX = me.getX();
            touchY = me.getY();
            widget = plot.getGraphWidget();
            gridRect = widget.getGridRect();
            if(gridRect.contains(touchX, touchY)){ //Check the touch event is in the grid
                XYSeries xyData = plot.getSeriesSet().iterator().next();
                long targetValX = Math.round(widget.getXVal(touchX));
                System.out.println("Touched at "   touchX   ", "   touchY   ". Target val X: "   targetValX);

                if(plot.getSeriesSet().size() > 1){
                    System.out.println("More than one series in plot. Using only the first one");
                }
                for(int i = 0; i < xyData.size();   i){
                    long currValX = xyData.getX(i).longValue();
                    long currValY = xyData.getY(i).longValue();

                    //Calculate the range value of the closest domain value (assumes xyData is sorted in ascending X order)
                    if(currValX >= targetValX){
                        long currDiff = currValX - targetValX; 
                        if(prevValX != null amp;amp; (targetValX - prevValX) < currDiff){
                            targetValY = xyData.getY(i-1).longValue();
                        }else{
                            targetValY = currValY;
                        }
                        break;
                    }
                    prevValX = currValX;
                }
                if(targetValY != null){
                    long maxValY = plot.getCalculatedMaxY().longValue();
                    long minValY = plot.getCalculatedMinY().longValue();
                    System.out.println("Target Y Value" targetValY);
                    float pixelPosY = gridRect.top   ValPixConverter.valToPix((double)targetValY, (double)minValY, (double)maxValY, (float)gridRect.height(), true);
                    System.out.println("Pixel Pos Y: " pixelPosY);

                    Number numberForDaily =  series2Numbers[ (int)targetValX];

                    widget.setDomainCursorPosition(touchX);
                    System.out.println("Touch X: " touchX);

                    plot.getGraphWidget().setSize(new SizeMetrics(
                            0, SizeLayoutType.FILL,
                            0, SizeLayoutType.FILL)

                            );


                    Paint paintForText = new Paint();
                    paintForText.setColor(Color.BLACK);

                    Paint paintForTextBackroud = new Paint();
                    paintForTextBackroud.setColor(Color.WHITE);


                    widget.setCursorLabelPaint(paintForText);
                    widget.setCursorLabelBackgroundPaint(paintForTextBackroud);
                    widget.getDomainLabelPaint().setTextSize(20);
                    widget.getRangeLabelPaint().setTextSize(20);
                    widget.getCursorLabelPaint().setTextSize(25);

                    System.out.println("Cursor is at = "  targetValX   " "   targetValY);

                    getTheStartDate();

                    Calendar cal = new GregorianCalendar(year, month   1, day);
                    Integer theNumberOfTheStartDay = cal.get(GregorianCalendar.DAY_OF_YEAR);

                   //the offset
                    Integer addingTheDates = (theNumberOfTheStartDay   (int)targetValX);

                    //convert number to a date which is readable
                   GregorianCalendar gcDate = new GregorianCalendar();
                   gcDate.set(GregorianCalendar.DAY_OF_YEAR, addingTheDates);


                   //if the day of the month is less than 10
                   //add a zero to the front of it so that the string can be ordered
                   if(gcDate.get(GregorianCalendar.DAY_OF_MONTH)<10){
                       StringBuilder sb = new StringBuilder();
                       sb.append("0");
                       sb.append(gcDate.get(GregorianCalendar.DAY_OF_MONTH));
                       fixZeroInDate = sb.toString();
                   }else{
                       fixZeroInDate= String.valueOf(gcDate.get(GregorianCalendar.DAY_OF_MONTH));
                   }


                   String stringOfFinalCycleDate=
                           (gcDate.get((GregorianCalendar.MONTH))) "/" 
                         fixZeroInDate "/" 
                          gcDate.get(GregorianCalendar.YEAR);



                   //UPDATING THE TEXTVIEWS BASED ON BUTTON TAP
                   cycleDate.setText(stringOfFinalCycleDate); //cycle date

                    cycleDay.setText(Long.toString(targetValX)); //cycle day

                   cycleDailyUsage.setText( numberForDaily.toString());//usage of single cycle day

                   System.out.println("Start time now");
                   //do math to get the running total of usage
                   findtheUsageSum(stringOfFinalCycleDate);
                   DecimalFormat df = new DecimalFormat("#0.00");
                   cycleOverallUsage.setText(String.valueOf(df.format(usageSumOnClick))); //overall usage by the cycle day
                 System.out.println("How much time has passed?");

                }else{
                    System.out.println("Couldn't find the closest range to the selected domain coordinate");
                }

                plot.invalidate();
            }else{
                System.out.println("Touched outside the plot grid");
            }

            return false;
        }

        private void findtheUsageSum(String stringOfFinalCycleDate) {

            ParseQuery<ParseObject> query3 = ParseQuery.getQuery("UsageCalculator");
             query3.whereEqualTo("SiteID", ShowSatellitesActivity.IDchosen);
             query3.addAscendingOrder("SiteID");
             query3.setLimit(10000);
             query3.whereLessThanOrEqualTo("usageDate", stringOfFinalCycleDate);
             query3.selectKeys(Arrays.asList("dataUsedString", "usageDate"));
             List<ParseObject> results1 = null;
            try {
                results1 = query3.find();
            } catch (ParseException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }

             usageSumOnClick = 0;
             System.out.println("query3 size: " results1.size());
             for (ParseObject data : results1) { 
                  // looping for all the dates and usage

                  System.out.println("data used: " data.getString("dataUsedString"));
                  System.out.println("on date: " data.getString("usageDate"));
                  usageSumOnClick = usageSumOnClick   Double.parseDouble(data.getString("dataUsedString"));

             } //ends for loop


        } //ends find the usage function

        private void getTheStartDate() {
             final Calendar calendar = Calendar.getInstance();

             year = calendar.get(Calendar.YEAR);
             month = calendar.get(Calendar.MONTH);
             day = 1;  

                    startDate = (month 1)  "-"  day  "-"  year;   

        }
    });
}
 

Комментарии:

1. Что происходит / не происходит? onProgressUpdate() Даже вызывается? И вам действительно нужно очистить этот код, чтобы он был более читабельным

2. Вызывается onProgressUpdateIs(), он просто не обновляет диалоговое окно.

Ответ №1:

Переопределите onProgressUpdate метод, который предоставляет вам AsyncTask, не создавайте свой собственный.

Кроме того, не называйте onProgressUpdate себя! Это метод обратного вызова, который используется системой для обеспечения обратного вызова вашего потока пользовательского интерфейса. Если вы вызовете его напрямую, код будет выполняться внутри фонового потока, где вы не сможете обновить пользовательский интерфейс. Вместо этого используйте publishProgress .

Редактировать: чтобы иметь возможность передавать правильное значение publishProgress , вам также необходимо указать общий тип при расширении AsyncTask (второй общий тип — это тип для выполнения).

Попробуйте сделать это так:

 private static class MyAsync extends AsyncTask <Void, Integer, String> {
....

@Override
protected void onProgressUpdate(Integer... progress) {
    alertDialog.setMessage("The graphs are loading...n" progress[0] "% Completed");
}

@Override
protected String doInBackground(Void... params) {
    incrementor = 0;
    for ( int i = 0; i<day; i  ){ 
        publishProgress(getThePercent);
        ....
 

Комментарии:

1. Спасибо, но у меня возникла проблема, из-за которой я ничего не могу передать в свою функцию publishProgress(). Знаете ли вы, как я могу разрешить publishProgress() принимать аргумент?

2. Изменить extends AsyncTask <Void, Void, String> на extends AsyncTask <Void, Integer, String>

3. Изменение того, что расширяет моя AsyncTask, помогло мне добавить аргумент в ‘onProgressUpdate (), так ЧТО СПАСИБО!!! Теперь у меня возникли проблемы, когда ‘onProgressUpdate ()’ вызывается / загружается после того, как все мои диаграммы уже загружены (что делает его бесполезным, потому что диалоговое окно предупреждения исчезает после загрузки диаграмм и никогда не попадает в мое диалоговое окно предупреждения). Есть ли какой-либо способ корректного обновления диалогового окна вовремя??? Спасибо!

4. Я пытался использовать таймер ожидания, но мне все еще не повезло. 🙁

5. Вы что-то делаете в потоке пользовательского интерфейса во время выполнения этой задачи?