在 Activty onBackPressed 中使用图表处理程序销毁片段
Destroy Fragment with Chart Handler inside Activty onBackPressed
我目前有一个 activity,其中包含 viewpager
和 fragments
。在这些 fragments
中的是从 URL 获取数据的图表。为了实现这一点,我必须添加一个 Handler
来延迟这个过程,这样应用程序就不会崩溃。没有它,数据加载速度不够快,所以我将它设置为 3 秒。我遇到的问题是,如果图表尚未加载,我 Backpress
应用程序会崩溃。
我已经尝试在我的 MainActivity
中实现 onBackPressed
的 override
方法,但这只会让应用程序在我回击时崩溃。我也尝试使用此处另一个问题中的此代码,但它也没有用。我真的不确定当我从我的活动回来时如何才能销毁 Handler
或 Fragment
。我该如何解决这个问题?
我使用的代码无效:
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getFragmentManager().popBackStack();
}
}
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coin_detail);
sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.graph_container);
setupViewPager(viewPager);
viewPager.setOffscreenPageLimit(10);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setText("1 Day");
tabLayout.getTabAt(1).setText("7 Days");
tabLayout.getTabAt(2).setText("30 Days");
TextView header = findViewById(R.id.newtextViewHead);
coinIMG = (ImageView) findViewById(R.id.imageView2);
button_alert = (CircleButton) findViewById(R.id.button);
button_fav = (CircleButton) findViewById(R.id.button_favorite);
//Calls for intent
Intent intent = getIntent();
//Tabs for fragment
private void setupViewPager(ViewPager viewPager){
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment_Graph1());
adapter.addFragment(new Fragment_Graph2());
adapter.addFragment(new Fragment_Graph3());
viewPager.setAdapter(adapter);
}
片段代码
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.graph1_fragment, container, false);
mChart = (LineChart) view.findViewById(R.id.chart1);
mChart.setNoDataText("Getting Data From Server");
mChart.setNoDataTextColor(Color.BLACK);
makeChart();
return view;
}
private void makeChart() {
StringRequest req = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
try {
jsonResponse = "";
JSONObject jObject = new JSONObject(response);
JSONArray jsonArray = jObject.getJSONArray("Data");
for (int i = 0; i <= jsonArray.length(); i++) {
JSONObject o = jsonArray.getJSONObject(i);
time = o.getString("time");
open = o.getString("close");
float val = Float.parseFloat(open);
yVals1.add(new Entry(i, val));
long unixSeconds = Long.parseLong(time);
Date date = new Date(unixSeconds * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("HH:MM");
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String formattedDate = sdf.format(date);
xValues.add(formattedDate);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
Graph_AppController.getInstance().addToRequestQueue(req);
handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mChart.setBackgroundColor(Color.WHITE);
mChart.setGridBackgroundColor(Color.WHITE);
mChart.setDrawGridBackground(true);
mChart.setDrawBorders(true);
Legend l = mChart.getLegend();
l.setEnabled(false);
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setTextColor(Color.BLACK);
xAxis.setValueFormatter(new DefaultAxisValueFormatter(0) {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return xValues.get((int) value % xValues.size());
}
@Override
public int getDecimalDigits() {
return 0;
}
});
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setTextColor(Color.BLACK);
leftAxis.setDrawAxisLine(true);
leftAxis.setDrawZeroLine(false);
leftAxis.setDrawGridLines(false);
leftAxis.setGridColor(Color.WHITE);
leftAxis.setAxisLineColor(Color.BLACK);
mChart.getAxisRight().setEnabled(false);
LineDataSet set1;
set1 = new LineDataSet(yVals1, "DataSet 1");
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
set1.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set1.setColor(Color.parseColor("#008000"));
set1.setDrawCircles(true);
set1.setLineWidth(3f);
set1.setCircleRadius(1f);
set1.setCircleColor(Color.parseColor("#008000"));
set1.setFillAlpha(50);
set1.setDrawFilled(true);
set1.setFillColor(Color.parseColor("#008000"));
set1.setHighLightColor(Color.rgb(244, 117, 117));
set1.setDrawCircleHole(false);
dataSets.add(set1);
LineData datab = new LineData(dataSets);
datab.setDrawValues(false);
mChart.setData(datab);
mChart.setDrawMarkers(true);
IMarker marker = new YourMarkerView(getContext(),R.layout.custom_marker);
mChart.setMarker(marker);
}
}, 3000);
}
public class YourMarkerView extends MarkerView {
private TextView tvContent;
public YourMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
// find your layout components
tvContent = (TextView) findViewById(R.id.tvContent);
}
// callbacks everytime the MarkerView is redrawn, can be used to update the
// content (user-interface)
@Override
public void refreshContent(Entry e, Highlight highlight) {
tvContent.setText("$" + e.getY());
// this will perform necessary layouting
super.refreshContent(e, highlight);
}
private MPPointF mOffset;
@Override
public MPPointF getOffset() {
if(mOffset == null) {
// center the marker horizontally and vertically
mOffset = new MPPointF(-(getWidth() / 2), -getHeight());
}
return mOffset;
}
@Override
public void draw(Canvas canvas, float posX, float posY) {
posX = 400;
posY = -30;
canvas.translate(posX,posY);
draw(canvas);
canvas.translate(-posX,-posY);
}
}
问题是您的片段存在内存泄漏。网络请求将 return 到一个不再存在的片段。您的处理程序将启动一个线程并尝试访问已被销毁的元素。你不应该使用固定时间的处理程序,如果你请求超过 3 秒到 return 怎么办?您只需要在收到结果时填写图表数据,将您的 makechart 方法更改为:
private void makeChart() {
StringRequest req = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
try {
jsonResponse = "";
JSONObject jObject = new JSONObject(response);
JSONArray jsonArray = jObject.getJSONArray("Data");
for (int i = 0; i <= jsonArray.length(); i++) {
JSONObject o = jsonArray.getJSONObject(i);
time = o.getString("time");
open = o.getString("close");
float val = Float.parseFloat(open);
yVals1.add(new Entry(i, val));
long unixSeconds = Long.parseLong(time);
Date date = new Date(unixSeconds * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("HH:MM");
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String formattedDate = sdf.format(date);
xValues.add(formattedDate);
}
//finished receiving data
fillChartData();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
Graph_AppController.getInstance().addToRequestQueue(req);
}
创建一个名为 fillChartData
的新方法,将所有处理程序代码移至此方法并在您完成接收数据后调用它。这样你就不必使用处理程序了。
public void fillChartData(){
mChart.setBackgroundColor(Color.WHITE);
mChart.setGridBackgroundColor(Color.WHITE);
mChart.setDrawGridBackground(true);
mChart.setDrawBorders(true);
Legend l = mChart.getLegend();
l.setEnabled(false);
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setTextColor(Color.BLACK);
xAxis.setValueFormatter(new DefaultAxisValueFormatter(0) {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return xValues.get((int) value % xValues.size());
}
@Override
public int getDecimalDigits() {
return 0;
}
});
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setTextColor(Color.BLACK);
leftAxis.setDrawAxisLine(true);
leftAxis.setDrawZeroLine(false);
leftAxis.setDrawGridLines(false);
leftAxis.setGridColor(Color.WHITE);
leftAxis.setAxisLineColor(Color.BLACK);
mChart.getAxisRight().setEnabled(false);
LineDataSet set1;
set1 = new LineDataSet(yVals1, "DataSet 1");
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
set1.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set1.setColor(Color.parseColor("#008000"));
set1.setDrawCircles(true);
set1.setLineWidth(3f);
set1.setCircleRadius(1f);
set1.setCircleColor(Color.parseColor("#008000"));
set1.setFillAlpha(50);
set1.setDrawFilled(true);
set1.setFillColor(Color.parseColor("#008000"));
set1.setHighLightColor(Color.rgb(244, 117, 117));
set1.setDrawCircleHole(false);
dataSets.add(set1);
LineData datab = new LineData(dataSets);
datab.setDrawValues(false);
mChart.setData(datab);
mChart.setDrawMarkers(true);
IMarker marker = new YourMarkerView(getContext(),R.layout.custom_marker);
mChart.setMarker(marker);
}
我目前有一个 activity,其中包含 viewpager
和 fragments
。在这些 fragments
中的是从 URL 获取数据的图表。为了实现这一点,我必须添加一个 Handler
来延迟这个过程,这样应用程序就不会崩溃。没有它,数据加载速度不够快,所以我将它设置为 3 秒。我遇到的问题是,如果图表尚未加载,我 Backpress
应用程序会崩溃。
我已经尝试在我的 MainActivity
中实现 onBackPressed
的 override
方法,但这只会让应用程序在我回击时崩溃。我也尝试使用此处另一个问题中的此代码,但它也没有用。我真的不确定当我从我的活动回来时如何才能销毁 Handler
或 Fragment
。我该如何解决这个问题?
我使用的代码无效:
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
//additional code
} else {
getFragmentManager().popBackStack();
}
}
MainActivity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_coin_detail);
sectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
viewPager = (ViewPager) findViewById(R.id.graph_container);
setupViewPager(viewPager);
viewPager.setOffscreenPageLimit(10);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.getTabAt(0).setText("1 Day");
tabLayout.getTabAt(1).setText("7 Days");
tabLayout.getTabAt(2).setText("30 Days");
TextView header = findViewById(R.id.newtextViewHead);
coinIMG = (ImageView) findViewById(R.id.imageView2);
button_alert = (CircleButton) findViewById(R.id.button);
button_fav = (CircleButton) findViewById(R.id.button_favorite);
//Calls for intent
Intent intent = getIntent();
//Tabs for fragment
private void setupViewPager(ViewPager viewPager){
SectionsPagerAdapter adapter = new SectionsPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new Fragment_Graph1());
adapter.addFragment(new Fragment_Graph2());
adapter.addFragment(new Fragment_Graph3());
viewPager.setAdapter(adapter);
}
片段代码
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.graph1_fragment, container, false);
mChart = (LineChart) view.findViewById(R.id.chart1);
mChart.setNoDataText("Getting Data From Server");
mChart.setNoDataTextColor(Color.BLACK);
makeChart();
return view;
}
private void makeChart() {
StringRequest req = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
try {
jsonResponse = "";
JSONObject jObject = new JSONObject(response);
JSONArray jsonArray = jObject.getJSONArray("Data");
for (int i = 0; i <= jsonArray.length(); i++) {
JSONObject o = jsonArray.getJSONObject(i);
time = o.getString("time");
open = o.getString("close");
float val = Float.parseFloat(open);
yVals1.add(new Entry(i, val));
long unixSeconds = Long.parseLong(time);
Date date = new Date(unixSeconds * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("HH:MM");
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String formattedDate = sdf.format(date);
xValues.add(formattedDate);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
Graph_AppController.getInstance().addToRequestQueue(req);
handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mChart.setBackgroundColor(Color.WHITE);
mChart.setGridBackgroundColor(Color.WHITE);
mChart.setDrawGridBackground(true);
mChart.setDrawBorders(true);
Legend l = mChart.getLegend();
l.setEnabled(false);
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setTextColor(Color.BLACK);
xAxis.setValueFormatter(new DefaultAxisValueFormatter(0) {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return xValues.get((int) value % xValues.size());
}
@Override
public int getDecimalDigits() {
return 0;
}
});
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setTextColor(Color.BLACK);
leftAxis.setDrawAxisLine(true);
leftAxis.setDrawZeroLine(false);
leftAxis.setDrawGridLines(false);
leftAxis.setGridColor(Color.WHITE);
leftAxis.setAxisLineColor(Color.BLACK);
mChart.getAxisRight().setEnabled(false);
LineDataSet set1;
set1 = new LineDataSet(yVals1, "DataSet 1");
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
set1.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set1.setColor(Color.parseColor("#008000"));
set1.setDrawCircles(true);
set1.setLineWidth(3f);
set1.setCircleRadius(1f);
set1.setCircleColor(Color.parseColor("#008000"));
set1.setFillAlpha(50);
set1.setDrawFilled(true);
set1.setFillColor(Color.parseColor("#008000"));
set1.setHighLightColor(Color.rgb(244, 117, 117));
set1.setDrawCircleHole(false);
dataSets.add(set1);
LineData datab = new LineData(dataSets);
datab.setDrawValues(false);
mChart.setData(datab);
mChart.setDrawMarkers(true);
IMarker marker = new YourMarkerView(getContext(),R.layout.custom_marker);
mChart.setMarker(marker);
}
}, 3000);
}
public class YourMarkerView extends MarkerView {
private TextView tvContent;
public YourMarkerView(Context context, int layoutResource) {
super(context, layoutResource);
// find your layout components
tvContent = (TextView) findViewById(R.id.tvContent);
}
// callbacks everytime the MarkerView is redrawn, can be used to update the
// content (user-interface)
@Override
public void refreshContent(Entry e, Highlight highlight) {
tvContent.setText("$" + e.getY());
// this will perform necessary layouting
super.refreshContent(e, highlight);
}
private MPPointF mOffset;
@Override
public MPPointF getOffset() {
if(mOffset == null) {
// center the marker horizontally and vertically
mOffset = new MPPointF(-(getWidth() / 2), -getHeight());
}
return mOffset;
}
@Override
public void draw(Canvas canvas, float posX, float posY) {
posX = 400;
posY = -30;
canvas.translate(posX,posY);
draw(canvas);
canvas.translate(-posX,-posY);
}
}
问题是您的片段存在内存泄漏。网络请求将 return 到一个不再存在的片段。您的处理程序将启动一个线程并尝试访问已被销毁的元素。你不应该使用固定时间的处理程序,如果你请求超过 3 秒到 return 怎么办?您只需要在收到结果时填写图表数据,将您的 makechart 方法更改为:
private void makeChart() {
StringRequest req = new StringRequest(Request.Method.GET, URL,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
Log.d(TAG, response.toString());
try {
jsonResponse = "";
JSONObject jObject = new JSONObject(response);
JSONArray jsonArray = jObject.getJSONArray("Data");
for (int i = 0; i <= jsonArray.length(); i++) {
JSONObject o = jsonArray.getJSONObject(i);
time = o.getString("time");
open = o.getString("close");
float val = Float.parseFloat(open);
yVals1.add(new Entry(i, val));
long unixSeconds = Long.parseLong(time);
Date date = new Date(unixSeconds * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("HH:MM");
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String formattedDate = sdf.format(date);
xValues.add(formattedDate);
}
//finished receiving data
fillChartData();
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
});
Graph_AppController.getInstance().addToRequestQueue(req);
}
创建一个名为 fillChartData
的新方法,将所有处理程序代码移至此方法并在您完成接收数据后调用它。这样你就不必使用处理程序了。
public void fillChartData(){
mChart.setBackgroundColor(Color.WHITE);
mChart.setGridBackgroundColor(Color.WHITE);
mChart.setDrawGridBackground(true);
mChart.setDrawBorders(true);
Legend l = mChart.getLegend();
l.setEnabled(false);
XAxis xAxis = mChart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(false);
xAxis.setAxisLineColor(Color.BLACK);
xAxis.setTextColor(Color.BLACK);
xAxis.setValueFormatter(new DefaultAxisValueFormatter(0) {
@Override
public String getFormattedValue(float value, AxisBase axis) {
return xValues.get((int) value % xValues.size());
}
@Override
public int getDecimalDigits() {
return 0;
}
});
YAxis leftAxis = mChart.getAxisLeft();
leftAxis.setTextColor(Color.BLACK);
leftAxis.setDrawAxisLine(true);
leftAxis.setDrawZeroLine(false);
leftAxis.setDrawGridLines(false);
leftAxis.setGridColor(Color.WHITE);
leftAxis.setAxisLineColor(Color.BLACK);
mChart.getAxisRight().setEnabled(false);
LineDataSet set1;
set1 = new LineDataSet(yVals1, "DataSet 1");
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
set1.setMode(LineDataSet.Mode.CUBIC_BEZIER);
set1.setColor(Color.parseColor("#008000"));
set1.setDrawCircles(true);
set1.setLineWidth(3f);
set1.setCircleRadius(1f);
set1.setCircleColor(Color.parseColor("#008000"));
set1.setFillAlpha(50);
set1.setDrawFilled(true);
set1.setFillColor(Color.parseColor("#008000"));
set1.setHighLightColor(Color.rgb(244, 117, 117));
set1.setDrawCircleHole(false);
dataSets.add(set1);
LineData datab = new LineData(dataSets);
datab.setDrawValues(false);
mChart.setData(datab);
mChart.setDrawMarkers(true);
IMarker marker = new YourMarkerView(getContext(),R.layout.custom_marker);
mChart.setMarker(marker);
}