内部类访问变量需声明final及GraphView绘图异常求助
解决GraphView与Firebase结合时的内部类变量访问及绘图异常问题
我来帮你搞定这两个问题——内部类变量访问的报错,以及绘图不符合预期的问题:
一、解决内部类访问变量的报错问题
你遇到的Variable 'graph' is accessed from within inner class, needs to be declared final.错误,本质是Java中匿名内部类的访问规则:匿名内部类只能访问**final或者实际不可变(effectively final)**的外部局部变量。
这里有两种简单的解决方式:
方式1:将graph和series声明为类成员变量
把这两个变量从onCreate的局部变量提升为类的成员,这样匿名内部类可以直接访问它们,不需要额外修饰:
public class RetrieveApp extends AppCompatActivity { Integer hrValue; ArrayList<Integer> array2; private ListView mListView; LineGraphSeries<DataPoint> series; GraphView graph; // 声明为类成员变量 FirebaseAuth auth; FirebaseUser user; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_retrieve_app); // 初始化类成员 graph = (GraphView)findViewById(R.id.graph); series = new LineGraphSeries<DataPoint>(); graph.addSeries(series); // 只需要添加一次series到图表 DatabaseReference userdatabase = FirebaseDatabase.getInstance().getReference().child("Users"); auth = FirebaseAuth.getInstance(); user = auth.getCurrentUser(); DatabaseReference ref = userdatabase.child(user.getUid()); array2 = new ArrayList<>(); // 监听Firebase数据变化 ref.child("hrvalue").child("nilaihr").addChildEventListener(new ChildEventListener() { @Override public void onChildAdded(DataSnapshot dataSnapshot, String s) { hrValue = dataSnapshot.child("tmpHR").getValue(Integer.class); showData(dataSnapshot); // 直接使用类成员的graph和series // 计算下一个x轴值,保证线条连续 double x = series.getHighestValueX() + 1; double y = hrValue; series.appendData(new DataPoint(x, y), true, 1000); } // 别忘了实现ChildEventListener的其他抽象方法 @Override public void onChildChanged(DataSnapshot dataSnapshot, String s) {} @Override public void onChildRemoved(DataSnapshot dataSnapshot) {} @Override public void onChildMoved(DataSnapshot dataSnapshot, String s) {} @Override public void onCancelled(DatabaseError databaseError) {} }); } // 你的showData方法实现 private void showData(DataSnapshot dataSnapshot) { // 这里写你展示数据的逻辑 } }
方式2:将局部变量标记为final(Java 8+可省略显式final)
如果你不想把变量提升为类成员,可以在onCreate里把graph和series标记为final(Java 8及以上版本中,只要变量后续不重新赋值,也可以不用显式写final):
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_retrieve_app); final GraphView graph = (GraphView)findViewById(R.id.graph); final LineGraphSeries<DataPoint> series = new LineGraphSeries<DataPoint>(); graph.addSeries(series); // 后续代码保持不变,内部类可直接访问这些final变量 }
二、修正绘图逻辑,实现连续线条
你原来的代码在onChildAdded里每次都新建series,还循环1000次添加同一个hrValue的点,这会导致每次新数据过来都覆盖之前的图表,而且画出来的是一堆重复的点,根本不是连续线条。
修正思路:
- 只在
onCreate里初始化一次series并添加到graph - 每次获取新的
hrValue时,计算一个递增的x轴值(比如基于已有数据的最大x值+1,或者用时间戳),然后调用appendData添加单个点即可
上面的代码示例已经包含了这个修正,用series.getHighestValueX() + 1来获取下一个x值,保证线条连续。如果需要更精确的时间轴,也可以用System.currentTimeMillis()作为x值(记得转成double类型)。
内容的提问来源于stack exchange,提问作者Astrid Gloria
相关产品推荐
相关产品推荐

