java - 为什么我的 Android PieChart 绘图行为异常并且在屏幕旋转时出现重复的切片?

标签 java android pie-chart screen-rotation

我需要一些帮助来解决这个问题。我有一个 PieChart,它是使用来自 MySQL db 的一些数据在我的 Android 应用程序中绘制的。我正在使用 AsyncTask 类实现,它从服务器加载数据,生成 HTTPPostRequest 并解析返回的 JSON 响应。图表效果很好并绘制在屏幕上。当我旋转设备的屏幕时,问题出现了:图表行为异常并再次绘制切片...我不知道为什么会这样做,但我读到,如果旋转屏幕, 的所有方法都会发生变化。 Activity 再次调用(onCreate()onStart()onResume() 方法)。或许是因为这个???但我不确定......这是它的样子:

enter image description here

然后当我旋转设备时:

enter image description here

数据重复!为什么?我错了什么?

这是所有代码:

public class ComeHaInvestito extends Activity {

/**** PieChartBuilder ****/
/** Colors to be used for the pie slices. */
private static int[] COLORS = new int[] { Color.GREEN, Color.BLUE, Color.MAGENTA, Color.CYAN };
/** The main series that will include all the data. */
private CategorySeries mSeries = new CategorySeries("");
/** The main renderer for the main dataset. */
private DefaultRenderer mRenderer = new DefaultRenderer();
/** Edit text field for entering the slice value. */
//private EditText mValue;
/** The chart view that displays the data. */
private GraphicalView mChartView;

private int HowmanyTimes;
@Override
protected void onRestoreInstanceState(Bundle savedState) {
   super.onRestoreInstanceState(savedState);
   mSeries = (CategorySeries) savedState.getSerializable("current_series");
   mRenderer = (DefaultRenderer) savedState.getSerializable("current_renderer");
}

  @Override
  protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable("current_series", mSeries);
    outState.putSerializable("current_renderer", mRenderer);
  }

/**** ComeHaInvestito ****/
// String which will store the values of the user 
String municipalityName;
String year;
String versedMoney;

// List<Item> ArrayList that will be used to store data from DB
List<Item> MasterAndDetailstatisticsInfoList;

private static final String TAG_COMUNE = "mun_name";
private static final String TAG_ANNO = "year";
private static final String TAG_VERSED_MONEY = "versed_money";
private static final String TAG_SUCCESS = "success";

// POST request information
private static final String URL_ANDROID_APP_LISTENER = "http://xxx.xxx.xxx.xxx/androidApp/AndroidListener.php";

private ProgressDialog pDialog; 
// JSONParser instance
JSONParser jParser = new JSONParser();

// JSON data retrieving information
private static final String JSON_STATISTICS_INFOS_LABEL = "statistics_infos";   
private static final String JSON_MASTER_LABEL = "master";
private static final String JSON_DETAIL_LABEL = "detail";
private static final String JSON_MASTER_DETAIL_NAME_LABEL = "name";
private static final String JSON_MASTER_DETAIL_VALUE_LABEL ="value";

// statistics info JSON Array which will contain the Master and Detail data that will come from the POST request
JSONArray statisticsInfo = null;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_come_ha_investito);
    Log.d("OnCREATE", "CREO L'ACTIVITY");
    // recovering data from previous actitity
    Intent iMieiDati = getIntent();
    this.municipalityName = iMieiDati.getStringExtra(TAG_COMUNE);
    this.year = iMieiDati.getStringExtra(TAG_ANNO);
    this.versedMoney = iMieiDati.getStringExtra(TAG_VERSED_MONEY);

    // instantiating the needed data structure
    MasterAndDetailstatisticsInfoList = new ArrayList<Item>();

    mRenderer.setStartAngle(270);
    mRenderer.setDisplayValues(true);

    new LoadAllMunicipalitiesInvestmentStatisticsThread().execute();

    //mRenderer.setZoomButtonsVisible(true);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.pie_chart_builder2, menu);
    return true;
}

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

    if (mChartView == null) {
      LinearLayout layout = (LinearLayout) findViewById(R.id.chart);
      mChartView = ChartFactory.getPieChartView(this, mSeries, mRenderer);
      mRenderer.setClickEnabled(true);
      mChartView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
          SeriesSelection seriesSelection = mChartView.getCurrentSeriesAndPoint();
          if (seriesSelection == null) {
            Toast.makeText(ComeHaInvestito.this, "No chart element selected", Toast.LENGTH_SHORT).show();
          } 
          else {
            for (int i = 0; i < mSeries.getItemCount(); i++) {
              mRenderer.getSeriesRendererAt(i).setHighlighted(i == seriesSelection.getPointIndex());
            }
           // mChartView.repaint();

            Toast.makeText(
                ComeHaInvestito.this,
                "Chart data point index " + seriesSelection.getPointIndex() + " selected"
                    + " point value=" + seriesSelection.getValue(), Toast.LENGTH_SHORT).show();

          }
        }
      });
      layout.addView(mChartView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
    } 
    else {
      //mChartView.repaint();
    }
  }


  private void initChart() {
        int i=0;
        double value=0;
        for (Item item : MasterAndDetailstatisticsInfoList) {
            if (i == 4) {
                break;
            }
            Log.d("Ciclo ", "NUMERO " + i);
            if (item.getViewType() == EntryType.MASTER.ordinal()) { 
                MasterWithValue master = (MasterWithValue) item;
                Log.d("MASTER NAME", master.getMasterName());
                Log.d("MASTER VALUE", master.getMasterValue());
                try {
                    value = Double.parseDouble(master.getMasterValue());
                } 
                catch (NumberFormatException e) {
                    // value is not a decimal
                }
                mSeries.add(master.getMasterName(), value);
                SimpleSeriesRenderer renderer = new SimpleSeriesRenderer();
                renderer.setColor(COLORS[i%4]);
                i++;
                mRenderer.addSeriesRenderer(renderer);
                Log.d("mSeries", mSeries.toString());
            }
        }
  }

/**** Background Thread ****/
public class LoadAllMunicipalitiesInvestmentStatisticsThread extends AsyncTask<String, String, String> {

    @Override 
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(ComeHaInvestito.this);
        pDialog.setMessage("Caricamento...");
        pDialog.setIndeterminate(false);
        pDialog.setCancelable(false);
        pDialog.show();         
    }

    @Override
    protected String doInBackground(String... args) {
        Log.d("ilMioComune", "Caricamento Statistiche Investimenti");
        // building the HTTP POST request
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair(TAG_COMUNE, municipalityName));
        params.add(new BasicNameValuePair(TAG_ANNO, year));
        params.add(new BasicNameValuePair(TAG_VERSED_MONEY, versedMoney));
        Log.d("params", params.toString());
        JSONObject json = jParser.makeHttpRequest(URL_ANDROID_APP_LISTENER, "POST", params);

        Log.d("JSON POST statistics investments", json.toString());
        try {
            int success = json.getInt(TAG_SUCCESS);

            if (success == 1) {

                statisticsInfo = json.getJSONArray(JSON_STATISTICS_INFOS_LABEL);

                // foreach Statistics Master Entry
                for (int i = 0; i<statisticsInfo.length(); i++) {
                    JSONObject JSONstatisticsInfo = statisticsInfo.getJSONObject(i);
                    JSONObject JSONmasterEntry = JSONstatisticsInfo.getJSONObject(JSON_MASTER_LABEL);

                    String masterEntryName = JSONmasterEntry.getString(JSON_MASTER_DETAIL_NAME_LABEL);
                    String masterEntryValue = JSONmasterEntry.getString(JSON_MASTER_DETAIL_VALUE_LABEL);
                    MasterAndDetailstatisticsInfoList.add(new MasterWithValue(masterEntryName, masterEntryValue));                      

                    JSONArray JSONdetails = JSONmasterEntry.getJSONArray(JSON_DETAIL_LABEL);
                    for (int j = 0; j<JSONdetails.length(); j++) {
                        JSONObject JSONdetailEntry = JSONdetails.getJSONObject(j);

                        String detailEntryName = JSONdetailEntry.getString(JSON_MASTER_DETAIL_NAME_LABEL);
                        String detailEntryValue = JSONdetailEntry.getString(JSON_MASTER_DETAIL_VALUE_LABEL);

                        MasterAndDetailstatisticsInfoList.add(new Detail(detailEntryName, detailEntryValue));
                    }
                }
            }
            else {
                // no statistics infos associated to the selected municipality were found
            }
        } 
        catch (JSONException e) {
            e.printStackTrace();
        }

        return null;
    }

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

        runOnUiThread(new Runnable() {

            @Override
            public void run() {
                String MasterAndDetails = MasterAndDetailstatisticsInfoList.toString();
                Log.d("List", MasterAndDetails);

                // Creating the pie chart using the data recovered from the DB
                 initChart();
            }
        });
    }
}
}

有人知道如何解决这个问题吗?

感谢关注!希望得到一些帮助!

最佳答案

你是正确的,只要你旋转,onCreate()onResume()等就会被调用。因此,您实际上要调用 new LoadAllMunicipalitiesInvestmentStatisticsThread().execute(); 两次。

您应该将数据初始化逻辑移至一处,并从savedInstanceState 加载该数据,或者在savedInstanceState 返回null 时调用初始化逻辑。

例如:

将声明更改为

private CategorySeries mSeries = null;

onCreate()

if(savedInstanceState != null)
  mSeries = (CategorySeries) savedInstanceState.getSerializable("current_series");

if(mSeries == null)
{
  mSeries = new CategorySeries("");
  new LoadAllMunicipalitiesInvestmentStatisticsThread().execute(); //this line can be substituted for a new init method, which would contain the thread.execute
}

关于java - 为什么我的 Android PieChart 绘图行为异常并且在屏幕旋转时出现重复的切片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22486960/

相关文章:

javascript - D3.js:现场旋转文本

javascript - 如何在 d3.js 中的圆形包装布局中插入饼图?

java - Hibernate标准,从实体A中选择,其中someId在B中

java - 用 thymeleaf 添加 css

Android Youtube API JSON-C 使用 GSON 解析

android - Activity 启动时随机抛出 IllegalStateException

java - 为什么 thymeleaf 中的无效反馈不起作用

java - 如何在java中的FileWriter中跳转一个字符?

android - 为什么 Navigation Drawer 项目模板 (Studio 3.6.1) 无法在 Android Nougat 上加载正确的 Controller ?

r - 如何提高饼图的可视化质量?