2015-08-03 3 views
0

Я пытаюсь создать приложение, в котором есть кнопка запуска и остановки, которая собирает данные акселерометра и отображает координаты x, y и z в таблицах. Каждый раз, когда датчик обнаруживает изменение, следует добавить строку с новым набором координат. Первоначально я не включал кнопки или метод onPause() или onResume(), и строки добавлялись бы динамически. Однако, поскольку добавлено столько строк, приложение замерзнет и разрядит батарею. В результате я добавил методы onPause и onResume, в дополнение к кнопке начала и остановки для записи данных. К сожалению, кнопки работают, но строки данных перестают меняться после того, как на экране полно строк. Я использовал LogCat для проверки того, что строки добавляются, и они есть. Я просто не знаю, почему они не все появляются. Мой код вставлен ниже. Файл макета после java-файла в том же блоке кода. Любая помощь будет принята с благодарностью!Мои динамически добавленные строки таблицы не отображаются в моем приложении

package com.explorer.extractor; 

    //import packages 

    import android.app.ActionBar; 
    import android.content.Context; 
    import android.graphics.Color; 
    import android.hardware.Sensor; 
    import android.hardware.SensorEvent; 
    import android.hardware.SensorEventListener; 
    import android.hardware.SensorManager; 
    import android.os.Bundle; 
    import android.support.v7.app.ActionBarActivity; 
    import android.util.Log; 
    import android.view.View; 
    import android.view.View.OnClickListener; 
    import android.widget.Button; 
    import android.widget.TableLayout; 
    import android.widget.TableRow; 
    import android.widget.TextView; 

    import java.io.BufferedReader; 
    import java.io.BufferedWriter; 
    import java.io.FileNotFoundException; 
    import java.io.IOException; 
    import java.io.InputStream; 
    import java.io.InputStreamReader; 
    import java.io.OutputStreamWriter; 
    import java.util.Calendar; 


    public class MainActivity extends ActionBarActivity implements SensorEventListener,OnClickListener { 

     Button button1; 
     Button button2; 

     private SensorManager mSensorManager; 
     Sensor accelerometer; 

     private static final String TAG = MainActivity.class.getName(); 
     private static final String FILENAME = "myFile.txt"; //file where data is written 

     //layout variables 
     TableLayout t1; 
     TextView dataReading; //declare data text object 
     Integer count = 0; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 

      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_main); 

      //initialize sensor manager 
      mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); 
      //initialize accelerometer 
      accelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); 
      //mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST); 

      t1 = (TableLayout) findViewById(R.id.main_table); 
      button1 = (Button) findViewById(R.id.button1); 
      button2 = (Button) findViewById(R.id.button2); 

      button1.setOnClickListener(this); 
      button2.setOnClickListener(this); 
     } 

     public void onAccuracyChanged(Sensor sensor, int accuracy){} 

     /**onResume() registers the accelerometer for listening 
     * to the events 
     */ 
     protected void onResume(){ 
      super.onResume(); 
      mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST); 
     } 

     protected void onPause(){ 
      super.onPause(); 
      mSensorManager.unregisterListener(this); 
     } 

     public void onSensorChanged(SensorEvent event){ 
      //if sensor status result is unreliable return 
      if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE){ 
       return; 
      } 

      Sensor sensor = event.sensor; 

      //check sensor type 
      if (sensor.getType() == Sensor.TYPE_ACCELEROMETER){ 
       //assign directions 
       float x = event.values[0]; 
       float y = event.values[1]; 
       float z = event.values[2]; 

       try { 
        //write to text file the x, y, and z values each type a sensor detects change 
        writeToFile(Float.toString(x), Float.toString(y), Float.toString(z)); 
        //return string of text file 
        String textFromFileString = readFromFile(); 
        TableRow tr = new TableRow(this); 
        if(count%2!=0) { 
         tr.setBackgroundColor(Color.GRAY); 
        } 
        tr.setId(100 + count); 
        tr.setLayoutParams(new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT, TableRow.LayoutParams.WRAP_CONTENT)); 

        //show data read from file 
        dataReading = new TextView(this); 
        dataReading.setId(200 + count); 
        dataReading.setText(textFromFileString); 
        dataReading.setPadding(2, 0, 5, 0); 
        dataReading.setTextColor(Color.WHITE); 
        tr.addView(dataReading); 
        //finally add data to table row 
        t1.addView(tr, new TableLayout.LayoutParams(ActionBar.LayoutParams.MATCH_PARENT, ActionBar.LayoutParams.WRAP_CONTENT)); 
        count++; 
        Log.i("LIMA","Add row. There are now " + t1.getChildCount()+"rows"); 
       }catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 

     } 

     public void onClick(View v) { 
      switch (v.getId()) { 
       case R.id.button1: 
        mSensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST); 
        break; 
       case R.id.button2: 
        mSensorManager.unregisterListener(this); 
      } 
     } 

     /** 
     * writeToFile: writes data recordings of accelerometer to text file 
     * @param x 
     * @param y 
     * @param z 
     * @throws IOException 
     */ 
     void writeToFile(String x, String y, String z) throws IOException { 
      //get exact instance of time in which call to write is being made 
      Calendar c = Calendar.getInstance(); 
      //create string to print to text using values in parameter 
      String s = c.get(Calendar.HOUR) + ":" + c.get(Calendar.MINUTE) + ":" + c.get(Calendar.SECOND) + ":" + c.get(Calendar.MILLISECOND) + " - " + "x: " + x + " y: " + y + " z: " + z + "\n"; 
      try { 
       //append new string to file 
       OutputStreamWriter outputStreamWriter = new OutputStreamWriter(openFileOutput(FILENAME, Context.MODE_PRIVATE)); 
       BufferedWriter bw = new BufferedWriter(outputStreamWriter); 
       bw.write(s); 
       bw.flush(); 
       bw.close(); 
      } catch(IOException e) { 
       Log.e(TAG, "File write failed: " + e.toString()); 
      } 
     } 

     private String readFromFile(){ 
      String ret = ""; 
      try { 
       //open text file to read from 
       InputStream inputStream = openFileInput(FILENAME); 
       if (inputStream != null) { 
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader); 
        String receiveString = ""; 
        StringBuilder stringBuilder = new StringBuilder(); 

        while ((receiveString = bufferedReader.readLine()) != null) { 
         //continue appending to stringBuilder until you've reached the end of file 
         stringBuilder.append(receiveString); 
        } 
        inputStream.close(); 
        ret = stringBuilder.toString(); 
       } 
      } catch (FileNotFoundException e) { 
       Log.e(TAG, "File not found: " + e.toString()); 
      } catch (IOException e) { 
       Log.e(TAG, "Can not read file: " + e.toString()); 
      } 
      return ret; 
     } 
    } 



    Here is my layout file: 

<?xml version="1.0" encoding="utf-8"?> 

<TableLayout 
xmlns:android="http://schemas.android.com/apk/res/android" 
android:id="@+id/main_table" 
    android:layout_weight="1" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:shrinkColumns="*" 
android:stretchColumns="*"> 

    <TableRow 
     android:id="@+id/tablerow" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content"> 

     <Button 
      android:id="@+id/button1" 
      android:layout_height="wrap_content" 
      android:text="Start" 
      android:layout_weight=".5" 
      android:layout_width="match_parent" 
      android:gravity="center_horizontal"/> 

     <Button 
      android:id="@+id/button2" 
      android:layout_height="wrap_content" 
      android:text="Stop" 
      android:layout_weight=".5" 
      android:layout_width="match_parent" 
      android:gravity="center_horizontal"/> 
    </TableRow> 
</TableLayout> 

ответ

0

Чтобы ответить на ваш вопрос: вам нужно обернуть TableLayout в ScrollView:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent"> 
    <TableLayout 
      android:id="@+id/main_table" 
    ... 

Однако Есть несколько проблем с кодом :-)

  • Возможно, большинство серьезный: не выполняйте ввода-вывода на основной нити. То есть не читайте/не записывайте файлы в основной поток/пользовательский интерфейс. Существует множество способов создания потоков в Android, но два примера: AsyncTask и RxJava/RxAndroid. Вы можете видеть, что это проблема в журнале LogCat, как:

    I/Choreographer﹕ Skipped 34 frames! The application may be doing too much work on its main thread. 
    
  • Это не очень хорошая идея, чтобы войти каждый случай получил, так как accellerometer события принимаются очень часто при использовании SensorManager.SENSOR_DELAY_FASTEST. Даже если вы уменьшаете частоту, все равно не стоит добавлять десятки тысяч записей в список пользовательского интерфейса. Вероятно, вы хотите показать только последнее количество записей и количество пользовательских интерфейсов, для которых вам не нужно больше 1 или 2 записей в секунду или что-то в этом роде, даже если вы хотите чаще регистрироваться в файле.

  • TextView dataReading не должно быть полем-членом - просто объявите его локальной переменной, где это необходимо. Всегда указывайте переменные как можно ближе к тому, где они используются.
  • Вы не используете TableLayout в качестве таблицы, достаточно обычного ListView.
  • Разбить код немного. Посмотрите на принцип единой ответственности. Как один случайный пример, материал обработки файлов может быть перенесен в отдельный класс.
  • Зачем вы записываете данные в текстовый файл, а затем снова читаете одни и те же данные из файла? Это лишний ввод-вывод :-) Вам вообще не нужно читать файл. (Предполагая, что у вас есть все основания писать в файл в первую очередь). И еще раз запомните: напишите в файл в фоновом потоке, используя AsyncTask или какой-нибудь другой механизм потоковой передачи.
  • Minor: быть совместимым с вашим полем наименования, либо использовать префикс «M» или нет, а затем придерживаться его :-)
  • Вы упускаете @Override аннотацию в нескольких местах, например, для onResume и .

удачи!

+0

Извините за задержанный ответ. Я просто хотел сказать, насколько я оценил вашу помощь! Как новичок в Android-разработке, вы понятия не имеете, насколько хорошо, когда профессионал разбивает его для вас. Еще раз спасибо! :) – CompSci1234

 Смежные вопросы

  • Нет связанных вопросов^_^