質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

1回答

983閲覧

フラグメントのインスタンスが破棄されたときにそのフラグメントがもつグラフデータのインスタンスを保持しておきたい

luckyclock

総合スコア73

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

0クリップ

投稿2021/11/30 13:38

編集2021/12/13 13:36

タブレイアウト+viewPagerにて
3タブフラグメントを構築しています。
タブ1ではMPChartを使用してグラフ描画しているのですが、
タブ1→タブ2→タブ3→タブ2→タブ1
と戻ってくるとタブ3に移動するとタブ1のフラグメントのインスタンスが消える関係で
タブ1フラグメントでもってるmChartのインスタンスも消えてしまい、
描画データがなくなってしまいます。
viewModelを使って書いてみましたが、タブ1→3→1で再描画されません。

MainActivity.java

java

1 2public class MainActivity extends AppCompatActivity { 3 4 private ActivityMainBinding binding; 5 private SectionsPagerAdapter sectionsPagerAdapter; 6 @Override 7 protected void onCreate(Bundle savedInstanceState) { 8 super.onCreate(savedInstanceState); 9 10 binding = ActivityMainBinding.inflate(getLayoutInflater()); 11 setContentView(binding.getRoot()); 12 13 sectionsPagerAdapter = new SectionsPagerAdapter(this, getSupportFragmentManager()); 14 ViewPager viewPager = binding.viewPager; 15 viewPager.setAdapter(sectionsPagerAdapter); 16 TabLayout tabs = binding.tabs; 17 tabs.setupWithViewPager(viewPager); 18 FloatingActionButton fab = binding.fab; 19 20 fab.setOnClickListener(new View.OnClickListener() { 21 @Override 22 public void onClick(View view) { 23 Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) 24 .setAction("Action", null).show(); 25 } 26 }); 27 28 feedMultiple(); 29 } 30 31 private Thread thread; 32 33 private void feedMultiple() { 34 35 if (thread != null) 36 thread.interrupt(); 37 38 final Runnable runnable = new Runnable() { 39 40 @Override 41 public void run() { 42 if( sectionsPagerAdapter.getCurrentFragment() instanceof GraphFragment) { 43 ((GraphFragment) sectionsPagerAdapter.getCurrentFragment()).setChart(); 44 } 45 } 46 }; 47 48 thread = new Thread(new Runnable() { 49 50 @Override 51 public void run() { 52 for (int i = 0; i < 1000; i++) { 53 54 // Don't generate garbage runnables inside the loop. 55 runOnUiThread(runnable); 56 57 try { 58 Thread.sleep(1000); 59 } catch (InterruptedException e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 }); 65 66 thread.start(); 67 } 68}

GraphFragment.java

java

1 2/** 3 * A placeholder fragment containing a simple view. 4 */ 5public class GraphFragment extends Fragment { 6 7 private PageViewModel pageViewModel; 8 private GraphFragmentBinding binding; 9 10 private LineChart chart; 11 private MainActivity activity; 12 13 public static GraphFragment newInstance() { 14 GraphFragment fragment = new GraphFragment(); 15 Bundle bundle = new Bundle(); 16// bundle.putInt(ARG_SECTION_NUMBER, index); 17 fragment.setArguments(bundle); 18 return fragment; 19 } 20 21 @Override 22 public void onCreate(Bundle savedInstanceState) { 23 super.onCreate(savedInstanceState); 24 activity = (MainActivity) getActivity(); 25 pageViewModel = new ViewModelProvider(activity).get(PageViewModel.class); 26 27 // Create the observer which updates the UI. 28 final Observer<LineChart> observer = new Observer<LineChart>() { 29 @Override 30 public void onChanged(@Nullable final LineChart newName) { 31 // Update the UI, in this case, a TextView. 32 addEntry(); 33 } 34 }; 35 36 // Observe the LiveData, passing in this activity as the LifecycleOwner and the observer. 37 pageViewModel.getLineChart().observe(this, observer); 38 } 39 40 @Override 41 public View onCreateView( 42 @NonNull LayoutInflater inflater, ViewGroup container, 43 Bundle savedInstanceState) { 44 45 binding = GraphFragmentBinding.inflate(inflater,container,false);; 46 View root = binding.getRoot(); 47 if(pageViewModel.getValue() == null){ 48 chart = binding.chart1; 49 initChart(); 50 } 51 else{ 52 chart = pageViewModel.getValue(); 53 } 54 55 return root; 56 } 57 58 @Override 59 public void onDestroyView() { 60 super.onDestroyView(); 61 binding = null; 62 } 63 64 public void setChart(){ 65 pageViewModel.setChart(chart); 66 } 67 68 public void initChart(){ 69 70 // enable description text 71 chart.getDescription().setEnabled(true); 72 73 // enable touch gestures 74 chart.setTouchEnabled(true); 75 76 // enable scaling and dragging 77 chart.setDragEnabled(true); 78 chart.setScaleEnabled(true); 79 chart.setDrawGridBackground(false); 80 81 // if disabled, scaling can be done on x- and y-axis separately 82 chart.setPinchZoom(true); 83 84 // set an alternative background color 85 chart.setBackgroundColor(Color.LTGRAY); 86 87 LineData data = new LineData(); 88 data.setValueTextColor(Color.WHITE); 89 90 // add empty data 91 chart.setData(data); 92 93 XAxis xl = chart.getXAxis(); 94 xl.setLabelRotationAngle(45); 95 xl.setTextColor(Color.WHITE); 96 xl.setDrawGridLines(false); 97 xl.setAvoidFirstLastClipping(true); 98 xl.setEnabled(true); 99 100 YAxis leftAxis = chart.getAxisLeft(); 101 leftAxis.setTextColor(Color.WHITE); 102 leftAxis.setAxisMaximum(100f); 103 leftAxis.setAxisMinimum(0f); 104 leftAxis.setDrawGridLines(true); 105 106 YAxis rightAxis = chart.getAxisRight(); 107 rightAxis.setEnabled(false); 108 } 109 110 public void addEntry() { 111 LineData data = chart.getData(); 112 113 if (data != null) { 114 115 ILineDataSet set = data.getDataSetByIndex(0); 116 // set.addEntry(...); // can be called as well 117 118 if (set == null) { 119 set = createSet(); 120 data.addDataSet(set); 121 } 122 123 data.addEntry(new Entry(set.getEntryCount(), (float) (Math.random() * 40) + 30f), 0); 124 data.notifyDataChanged(); 125 126 // let the chart know it's data has changed 127 chart.notifyDataSetChanged(); 128 129 // limit the number of visible entries 130 chart.setVisibleXRangeMaximum(120); 131 // chart.setVisibleYRange(30, AxisDependency.LEFT); 132 133 // move to the latest entry 134 chart.moveViewToX(data.getEntryCount()); 135 136 // this automatically refreshes the chart (calls invalidate()) 137 // chart.moveViewTo(data.getXValCount()-7, 55f, 138 // AxisDependency.LEFT); 139 } 140 } 141 142 private LineDataSet createSet() { 143 144 LineDataSet set = new LineDataSet(null, "Dynamic Data"); 145 set.setAxisDependency(AxisDependency.LEFT); 146 set.setColor(ColorTemplate.getHoloBlue()); 147 set.setCircleColor(Color.WHITE); 148 set.setLineWidth(2f); 149 set.setCircleRadius(4f); 150 set.setFillAlpha(65); 151 set.setFillColor(ColorTemplate.getHoloBlue()); 152 set.setHighLightColor(Color.rgb(244, 117, 117)); 153 set.setValueTextColor(Color.WHITE); 154 set.setValueTextSize(9f); 155 set.setDrawValues(false); 156 return set; 157 } 158} 159

pageViewModel.java

java

1package com.example.myapplication.ui.main; 2 3import androidx.arch.core.util.Function; 4import androidx.lifecycle.LiveData; 5import androidx.lifecycle.MutableLiveData; 6import androidx.lifecycle.Transformations; 7import androidx.lifecycle.ViewModel; 8 9import com.github.mikephil.charting.charts.LineChart; 10import com.github.mikephil.charting.data.LineData; 11 12public class PageViewModel extends ViewModel { 13 14 private MutableLiveData<Integer> mIndex = new MutableLiveData<>(); 15 16 private MutableLiveData<LineChart> myLineChart = new MutableLiveData<>(); 17 18 private LiveData<String> mText = Transformations.map(mIndex, new Function<Integer, String>() { 19 @Override 20 public String apply(Integer input) { 21 return "Hello world from section: " + input; 22 } 23 }); 24 25 public void setIndex(int index) { 26 mIndex.setValue(index); 27 } 28 29 public LiveData<String> getText() { 30 return mText; 31 } 32 33 public void setChart(LineChart m){ 34 myLineChart.setValue(m); 35 } 36 37 public LiveData<LineChart> getLineChart() { 38 if (myLineChart == null) { 39 myLineChart = new MutableLiveData<LineChart>(); 40 } 41 return myLineChart; 42 } 43 44 public LineChart getValue(){ 45 return myLineChart.getValue(); 46 } 47}

fragment_graph.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:orientation="vertical" android:layout_width="match_parent" 4 android:layout_height="wrap_content"> 5 6 7 <com.github.mikephil.charting.charts.LineChart 8 android:id="@+id/line_chart" 9 android:layout_width="match_parent" 10 android:layout_height="match_parent" 11 /> 12 13 14</LinearLayout>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jimbe

2021/11/30 14:04

ViewModel を使うのが普通(?)かと思いますが…mChart は View ですので、そのままは保持しないようにご注意です。
luckyclock

2021/12/12 11:15

viewModelに対応しようとしているのですが、いまいち理解しきれていないせいかわからない部分があります。 private LineChart mChartはviewModelの方のLiveDataとして持たせないということでしょうか?
jimbe

2021/12/12 15:21 編集

御存知のように Fragment は基本的に非表示になればシステムによって破棄されます。これは同時に、Fragment に表示されていた各 View も破棄されるということです。 ViewModel は Fragment よりも長生きさせることが出来ますのでデータの保存先とすることが出来るのですが、 それが Fragment の View を保持してしまうと、 Fragment が消された後も無意味な View を保持している状況が起こり得て、もしその View から Fragment の Context 等も持っていると、結果的に破棄されるはずの Fragment 全部のメモリイメージを保持してしまう "メモリリーク" となる可能性があります。 ですので、 ViewModel にはデータのみを保存し、 LiveData で observe されてデータが取り出される (=Fragment が主体となってデータを取り出す)ように作る必要があります。
jimbe

2021/12/12 15:13

ViewModel のサンプルとしましては、 AndroidStudio をお使いであれば New Project 時の雛形の中に ViewModel のものがあると思います。 ただ、確か ViewModel を Fragment に保存していたので、結局 Fragment 破棄と同時に ViewModel も破棄されてしまっていたと記憶しています。 ViewModel を Fragment より長生きさせるには、 ViewModel を Activity に保存する必要があります。 ですので、AndroidStudio の雛形は ViewModel の作り方やアクセスの仕方程度のサンプルにしかならないかもしれません。
luckyclock

2021/12/13 13:39

AndroidStudio のviewModelを参考にプログラムを変更しました。 タブ移動でグラフが描画されません。 >ViewModel を Activity に保存する必要があります。 pageViewModel = new ViewModelProvider(activity).get(PageViewModel.class); このメソッドでViewModelProvider(activity)とするとメインと紐づいてIDかわらないという記事をみたのでpageViewModel はフラグメント内で宣言しています。
jimbe

2021/12/13 15:27

まず、上で書きました通り、 LineChart は View ですので、 ViewModel に持たせてはいけません。恐らく LineData か、いっそ Entry レベルの別形式の List として持たせたほうが良いかと思います。 他に、 AndroidStudio の雛形が悪いのですが、 Fragment は onCreate や onCreateView には(ごく一部以外) ロジックを書かず、 onViewCreated を使うことになってきています。 またこれは全く個人的意見ですが、同じく AndroidStudio の雛形として作られる ViewBinding は、 コードが増える割に役に立ちません。一応実行時エラーとなる案件がコンパイルエラーとして検出できるようになる…という謳い文句がありますが、テスト実行すれば大抵分かる事です。ですので、素直に FindViewById を使ったほうが分かり易いかと思います。 ViewModel の取得は、 Activity でやらなくても Fragment でやった時点で無ければ作成されると思います。 修正されたコードではスレッドで定期的にフラグメントからデータを取得させる?ような感じになっていますが、そうでは無く、定期的に ViewModel の LiveData を更新することで、その LiveData を observe している フラグメントがデータを取得する形にするのが、 LiveData の存在意義です。 このようにすると、データを生成する側は自身のタイミングでデータを更新し、 Fragment 側は observe することでデータが更新されたことを察知して最新のデータを取得することが出来ます。 一応回答用にコードを作成しているのですが、データの生成部分をどうするかで考えています。 1秒ごとに現在秒(X)と乱数データ(Y) を生成する感じで大丈夫でしょうか。
guest

回答1

0

ベストアンサー

以下の感じで4分間ダミーデータがグラフに表示されます。
MPAndroidChart の仕様を確認していませんので、 setEntries のデータの更新部分が(MPAndroidChart を分かっている人からすると)ダメかもしれません。
ViewPager を ViewPager2 にしています。

MainActivity.java

java

1package com.teratail.q371702; 2 3import android.os.*; 4import android.util.Log; 5 6import com.google.android.material.tabs.*; 7 8import androidx.appcompat.app.AppCompatActivity; 9import androidx.lifecycle.ViewModelProvider; 10import androidx.viewpager2.widget.ViewPager2; 11 12import java.util.Random; 13 14public class MainActivity extends AppCompatActivity { 15 private MainViewModel vm; 16 17 @Override 18 protected void onCreate(Bundle savedInstanceState) { 19 super.onCreate(savedInstanceState); 20 setContentView(R.layout.activity_main); 21 22 vm = new ViewModelProvider(this).get(MainViewModel.class); 23 24 ViewPager2 viewPager2 = findViewById(R.id.view_pager2); 25 viewPager2.setAdapter(new MainPagerAdapter(this)); 26 27 TabLayout tabLayout = findViewById(R.id.tab_layout); 28 new TabLayoutMediator(tabLayout, viewPager2, 29 (tab,position) -> tab.setText(MainPagerAdapter.TAB_TITLES[position]) //タブタイトル 30 ).attach(); 31 32 feedMultiple(); 33 } 34 35 @Override 36 protected void onDestroy() { 37 super.onDestroy(); 38 if (thread != null) thread.interrupt(); 39 } 40 41 private Thread thread; 42 43 void feedMultiple() { 44 if (thread != null) thread.interrupt(); 45 Handler handler = new Handler(getMainLooper()); 46 thread = new Thread(new Runnable() { 47 Random random = new Random(); 48 @Override 49 public void run() { 50 Log.d("","start."); 51 for (int i=0; i<MainViewModel.DATA_COUNT_MAX*2; i++) { 52 long time = System.currentTimeMillis(); 53 float value = (float)(Math.random()*40); 54 handler.post(() -> vm.setValue(time, value)); 55 try { 56 Thread.sleep(1000); 57 } catch (InterruptedException e) { 58 break; 59 } 60 } 61 Log.d("","end."); 62 } 63 }); 64 thread.start(); 65 } 66}

res/layout/activity_main.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<androidx.coordinatorlayout.widget.CoordinatorLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 xmlns:app="http://schemas.android.com/apk/res-auto" 5 xmlns:tools="http://schemas.android.com/tools" 6 android:layout_width="match_parent" 7 android:layout_height="match_parent" 8 tools:context=".MainActivity"> 9 10 <com.google.android.material.appbar.AppBarLayout 11 android:layout_width="match_parent" 12 android:layout_height="wrap_content" 13 android:theme="@style/Theme.Q371702.AppBarOverlay"> 14 15 <TextView 16 android:id="@+id/title" 17 android:layout_width="wrap_content" 18 android:layout_height="wrap_content" 19 android:gravity="center" 20 android:minHeight="?actionBarSize" 21 android:padding="@dimen/appbar_padding" 22 android:text="@string/app_name" 23 android:textAppearance="@style/TextAppearance.Widget.AppCompat.Toolbar.Title" /> 24 25 <com.google.android.material.tabs.TabLayout 26 android:id="@+id/tab_layout" 27 android:layout_width="match_parent" 28 android:layout_height="wrap_content" /> 29 30 </com.google.android.material.appbar.AppBarLayout> 31 32 <androidx.viewpager2.widget.ViewPager2 33 android:id="@+id/view_pager2" 34 android:layout_width="match_parent" 35 android:layout_height="match_parent" 36 app:layout_behavior="@string/appbar_scrolling_view_behavior" /> 37 38</androidx.coordinatorlayout.widget.CoordinatorLayout>

MainPagerAdapter.java

java

1package com.teratail.q371702; 2 3import androidx.annotation.*; 4import androidx.fragment.app.*; 5import androidx.viewpager2.adapter.FragmentStateAdapter; 6 7public class MainPagerAdapter extends FragmentStateAdapter { 8 static final String TAB_TITLES[] = new String[]{"TAB A","TAB B","Graph"}; 9 10 public MainPagerAdapter(FragmentActivity fa) { 11 super(fa); 12 } 13 14 @NonNull 15 @Override 16 public Fragment createFragment(int position) { 17 switch(position) { 18 default: return new DummyFragment(); 19 case 0: return new ControlFragment(); 20 case 2: return new GraphFragment(); 21 } 22 } 23 24 @Override 25 public int getItemCount() { 26 return TAB_TITLES.length; 27 } 28}

MainViewModel.java

java

1package com.teratail.q371702; 2 3import androidx.lifecycle.*; 4 5import java.util.*; 6 7class RawData { 8 final long time; 9 final float value; 10 RawData(long time, float value) { 11 this.time = time; 12 this.value = value; 13 } 14} 15 16public class MainViewModel extends ViewModel { 17 static final int DATA_COUNT_MAX = 120; 18 19 private MutableLiveData<List<RawData>> rawDataLiveData = new MutableLiveData<>(Collections.emptyList()); 20 LiveData<List<RawData>> getValue() { 21 return rawDataLiveData; 22 } 23 24 void setValue(long time, float value) { 25 List<RawData> newList = new ArrayList(rawDataLiveData.getValue()); 26 newList.add(new RawData(time, value)); 27 while(newList.size() > DATA_COUNT_MAX) newList.remove(0); 28 rawDataLiveData.setValue(Collections.unmodifiableList(newList)); 29 } 30}

GraphFragment.java

java

1package com.teratail.q371702; 2 3import android.graphics.Color; 4import android.os.Bundle; 5import android.view.LayoutInflater; 6import android.view.View; 7import android.view.ViewGroup; 8 9import androidx.annotation.NonNull; 10import androidx.annotation.Nullable; 11import androidx.fragment.app.Fragment; 12import androidx.lifecycle.ViewModelProvider; 13 14import com.github.mikephil.charting.charts.LineChart; 15import com.github.mikephil.charting.components.XAxis; 16import com.github.mikephil.charting.components.YAxis; 17import com.github.mikephil.charting.components.YAxis.AxisDependency; 18import com.github.mikephil.charting.data.Entry; 19import com.github.mikephil.charting.data.LineData; 20import com.github.mikephil.charting.data.LineDataSet; 21import com.github.mikephil.charting.formatter.ValueFormatter; 22import com.github.mikephil.charting.utils.ColorTemplate; 23 24import java.text.SimpleDateFormat; 25import java.util.*; 26 27public class GraphFragment extends Fragment { 28 private MainViewModel mainViewModel; 29 private LineChart chart; 30 31 private static class DateXAxisFormatter extends ValueFormatter { 32 private SimpleDateFormat sdf = new SimpleDateFormat("MM:dd:ss"); 33 private List<Long> xAxis = new ArrayList<>(); 34 35 void clear() { xAxis.clear(); } 36 void add(long time) { xAxis.add(time); } 37 38 @Override 39 public String getFormattedValue(float value){ 40 int i = (int)value; 41 if(i < 0 || xAxis.size() <= i) return "-"; //ガード 42 return sdf.format(new Date(xAxis.get(i))); 43 } 44 } 45 private DateXAxisFormatter dateXAxisFormatter = new DateXAxisFormatter(); 46 47 @Override 48 public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 49 return inflater.inflate(R.layout.fragment_graph, container, false); 50 } 51 52 @Override 53 public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 54 super.onViewCreated(view, savedInstanceState); 55 56 mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class); 57 mainViewModel.getValue().observe(getViewLifecycleOwner(), rawDataList -> setEntries(rawDataList)); 58 59 chart = view.findViewById(R.id.line_chart); 60 initChart(); 61 } 62 63 public void initChart(){ 64 65 chart.getDescription().setEnabled(true); 66 chart.setTouchEnabled(true); 67 chart.setDragEnabled(true); 68 chart.setScaleEnabled(true); 69 chart.setDrawGridBackground(false); 70 chart.setPinchZoom(true); 71 chart.setBackgroundColor(Color.LTGRAY); 72 73 LineData data = new LineData(); 74 data.setValueTextColor(Color.WHITE); 75 chart.setData(data); 76 77 XAxis xl = chart.getXAxis(); 78 xl.setTextColor(Color.WHITE); 79 xl.setDrawGridLines(false); 80 xl.setAvoidFirstLastClipping(true); 81 xl.setEnabled(true); 82 xl.setValueFormatter(dateXAxisFormatter); //X軸のラベルを時刻にする 83 84 YAxis leftAxis = chart.getAxisLeft(); 85 leftAxis.setTextColor(Color.WHITE); 86 leftAxis.setAxisMaximum(100f); 87 leftAxis.setAxisMinimum(0f); 88 leftAxis.setDrawGridLines(true); 89 90 YAxis rightAxis = chart.getAxisRight(); 91 rightAxis.setEnabled(false); 92 } 93 94 public void setEntries(List<RawData> rawDataList) { 95 LineData data = chart.getData(); 96 if(data != null) { 97 98 data.clearValues(); 99 data.addDataSet(createSet()); 100 dateXAxisFormatter.clear(); 101 for(int i=0; i<rawDataList.size(); i++) { 102 RawData rawData = rawDataList.get(i); 103 dateXAxisFormatter.add(rawData.time); 104 data.addEntry(new Entry(i, rawData.value), 0); 105 } 106 data.notifyDataChanged(); 107 108 chart.notifyDataSetChanged(); 109 chart.setVisibleXRangeMaximum(MainViewModel.DATA_COUNT_MAX); 110 chart.moveViewToX(data.getEntryCount()); 111 } 112 } 113 114 private LineDataSet createSet() { 115 LineDataSet set = new LineDataSet(null, "Dynamic Data"); 116 set.setAxisDependency(AxisDependency.LEFT); 117 set.setColor(ColorTemplate.getHoloBlue()); 118 set.setCircleColor(Color.WHITE); 119 set.setLineWidth(2f); 120 set.setCircleRadius(4f); 121 set.setFillAlpha(65); 122 set.setFillColor(ColorTemplate.getHoloBlue()); 123 set.setHighLightColor(Color.rgb(244, 117, 117)); 124 set.setValueTextColor(Color.WHITE); 125 set.setValueTextSize(9f); 126 set.setDrawValues(false); 127 return set; 128 } 129}

res/layout/fragment_graph.xml

xml

1<?xml version="1.0" encoding="utf-8"?> 2<com.github.mikephil.charting.charts.LineChart 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:id="@+id/line_chart" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" />

※ DummyFragment, ControlFragment のコード・レイアウトは省略

投稿2021/12/13 16:37

編集2021/12/14 10:38
jimbe

総合スコア12648

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

luckyclock

2021/12/14 14:30

うまく実装できました。 結局シンプルにデータの部分をview modelにもたせて サイズ分addすればよかったのですね。 ようやく使い方が見えてきて応用できそうな気がしてきました。 時間表示の部分もありがとうございます。 最後までお付き合いいただき感謝です。
jimbe

2021/12/15 06:19

根本的な見方の転換の部分を書いていませんでしたが、「ビュー(フラグメント)に表示しているデータを、(再表示時にまた表示されるように)モデルに保存する」のでは無く、「モデルが保持してるデータを、ビューが必要時(ビューの初期表示時やデータが更新された時)に表示する」ということです。 ですので、モデルは(ビューの状態・有無さえ関係無く)データの保持・更新に注力でき、ビューは任意に LiveData の機能を使ってデータを得て表示できます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問