我动态添加的表行没有出现在我的应用中

时间:2015-08-03 18:35:10

标签: android button layout accelerometer tablerow

我正在尝试创建一个具有开始和停止按钮的应用程序,该按钮收集加速度计数据并在表格中显示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>

1 个答案:

答案 0 :(得分: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"
    ...

但是,您的代码存在一些问题: - )

  • 可能最严重的是:不要在主线程上执行任何I / O.即不读/写主/ UI线程上的文件。在Android中创建线程有很多种方法,但有两个例子是AsyncTask和RxJava / RxAndroid。您可以在logcat日志中看到这是一个问题,例如:

    I/Choreographer﹕ Skipped 34 frames!  The application may be doing too much work on its main thread.
    
  • 记录收到的每个事件并不是一个好主意,因为当您使用SensorManager.SENSOR_DELAY_FASTEST时,会非常频繁地收到accellerometer事件。即使您降低了频率,在UI列表中添加成千上万的条目仍然不是一个好主意。您可能只想显示最后x个条目,并且出于UI目的,即使您想要登录文件,您也不需要每秒1或2个条目或类似的东西。更频繁。

  • TextView dataReading不应该是成员字段 - 只需将其声明为需要的本地变量。始终声明变量尽可能接近它们的使用位置。
  • 您没有将TableLayout用作表格,常规ListView就足够了。
  • 稍微破解代码。看一下单一责任原则。就像一个随机的例子,文件处理的东西可以移到一个单独的类。
  • 为什么要将数据写入文本文件,然后再次从文件中读取相同的数据?这是不必要的I / O :-)您根本不需要阅读该文件。 (假设你有充分的理由首先写入文件)。并再次记住:使用AsyncTask或其他一些线程机制在后台线程中写入文件。
  • 轻微:与你的领域命名一致,要么使用&#34; m&#34;前缀与否,然后坚持: - )
  • 您在几个地方错过了@Override注释,例如适用于onResumeonPause
祝你好运!