【问题标题】:How to save a List from an Adapter to a xml File in Android?如何将列表从适配器保存到 Android 中的 xml 文件?
【发布时间】:2014-03-06 20:38:50
【问题描述】:

我开发了一个能够检测 BLE 信号和其他参数的应用程序。我使用 BaseAdapter 开发 ListView 以显示每个项目。问题是我想在扫描完成后将这些数据保存在一个 xml 文件中(在我建立了一段时间之后),但我不知道该怎么做。

在本课程中,我进行 BLE 扫描,并且当列表经过扫描时间后,我想在其中启动保存列表的过程:

public class ScanBleActivity extends ScanBaseActivity {

private BluetoothAdapter mBluetoothAdapter;
private boolean mScanning;
private Handler mHandler = new Handler();
//private List<BluetoothDevice> mydata;

// Stops scanning after 10 seconds.
private static final long SCAN_PERIOD = 20000;

/* (non-Javadoc)
 * @see com.zishao.bletest.ScanBaseActivity#initScanBluetooth()
 */
protected void initScanBluetooth() {
    BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
    mBluetoothAdapter = manager.getAdapter();
    startScanLen(true);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (mScanning) {
        startScanLen(false);
    }
}

/**
 * 
 * @param enable
 */
private void startScanLen(final boolean enable) {
    if (enable) {
        // Stops scanning after a pre-defined scan period.
        mHandler.postDelayed(new Runnable() {
            @Override
            public void run() {
                mScanning = false;
                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                try {
                    savedata(true);
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }, SCAN_PERIOD);

        mScanning = true;
        mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
        mScanning = false;
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
}

这是我的适配器:

public class LeDeviceListAdapter extends BaseAdapter {
public List<BluetoothDevice> data;
private Activity context;
private final HashMap<BluetoothDevice, Integer> rssiMap = new HashMap<BluetoothDevice, Integer>();



public LeDeviceListAdapter(Activity context, List<BluetoothDevice> data) {
    this.data = data;
    this.context = context;

}
//public static List<BluetoothDevice> getAllData() {
//  return data;
//}

public synchronized void addDevice(BluetoothDevice device, int rssi) {
    if(!data.contains(device) ){
    data.add(device);
    }
    rssiMap.put(device, rssi);
}

@Override
public int getCount() {
    return data.size();
}

@Override
public Object getItem(int position) {
    return data.get(position);
}

@Override
public long getItemId(int position) {
    return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (null == convertView) {
        LayoutInflater mInflater =
            (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        convertView = mInflater.inflate(R.layout.leaf_devices_list_item, null);
        convertView.setTag(new DeviceView(convertView));
    }
    DeviceView view = (DeviceView) convertView.getTag();
    view.init((BluetoothDevice) getItem(position));
    return convertView;
}

public class DeviceView {



    private TextView title;
    private TextView status;
    private TextView type;
    private TextView address;
    private TextView rssivalue;

    public DeviceView(View view) {
        title = (TextView) view.findViewById(R.id.device_name);
        status = (TextView) view.findViewById(R.id.device_status_txt);
        type = (TextView) view.findViewById(R.id.device_type_txt);
        address = (TextView) view.findViewById(R.id.device_address_txt);
        rssivalue = (TextView) view.findViewById(id.signal_intensity_txt);
    }

    public void init(BluetoothDevice device) {
        title.setText(device.getName());
        address.setText(device.getAddress());
        setType(device.getType());
        setStatus(device.getBondState());
        rssivalue.setText(""+rssiMap.get(device)+" dBm");

    }

    public void setType(int status) {
        switch(status) {
        case BluetoothDevice.DEVICE_TYPE_CLASSIC:
            type.setText("Bluetooth Signal");
            break;
        case BluetoothDevice.DEVICE_TYPE_LE:
            type.setText("BLE Signal");
            break;
        case BluetoothDevice.DEVICE_TYPE_DUAL:
            type.setText("Dual Mode - BR/EDR/LE");
            break;
        case BluetoothDevice.DEVICE_TYPE_UNKNOWN:
            type.setText("Device Unknown");
            break;
        }
    }

    public void setStatus(int s) {
        switch(s) {
        case BluetoothDevice.BOND_NONE:
            status.setText("Not Bonded");
            break;
        case BluetoothDevice.BOND_BONDED:
            status.setText("Bonded");
            break;
        case BluetoothDevice.BOND_BONDING:
            status.setText("Bonding");
            break;
        }
    }


}

我想将扫描过程中发现的每个 BLE 信号的标题、地址、类型、状态和 rssivalue(如上代码所示)保存在 xml 文件中。我只提供了项目的一部分,但如果有必要,我将编辑并放置缺少的代码。

有人知道怎么做吗??请帮忙!!!!!!

新代码:这对应于类ScanBaseActivity:

abstract public class ScanBaseActivity extends ListActivity {

protected LeDeviceListAdapter mLeDeviceListAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_devices_scan);
    mLeDeviceListAdapter = new LeDeviceListAdapter(this, new ArrayList<BluetoothDevice>());
    this.setListAdapter(mLeDeviceListAdapter);
    initScanBluetooth();
}

/**
 * Start Scan Bluetooth
 * 
 */
abstract protected void initScanBluetooth();

@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
    BluetoothDevice device = (BluetoothDevice) mLeDeviceListAdapter.getItem(position);
    ParcelUuid[] uuids = device.getUuids();
    String uuidString = "Getting UUID's from " + device.getName() + ";UUID:";
    if (null != uuids && uuids.length > 0) {
        uuidString += uuids[0].getUuid().toString();
    } else {
        uuidString += "empty";
    }
    Toast.makeText(this, uuidString, Toast.LENGTH_LONG).show();
}

/**
 * @param device
 */
protected synchronized void addDevice(final BluetoothDevice device, final int rssi) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mLeDeviceListAdapter.addDevice(device, rssi);
            mLeDeviceListAdapter.notifyDataSetChanged();
        }
    });
}

protected void savedata(boolean enable) throws FileNotFoundException{

        String filename = "file.txt";

        FileOutputStream fos;
        Bundle extras = getIntent().getExtras();
        long timestamp = extras.getLong("currentTime");
        try {
        fos= openFileOutput(filename, Context.MODE_PRIVATE);
        ObjectOutputStream out = new ObjectOutputStream(fos);
        out.write((int) timestamp);
        out.writeObject(mLeDeviceListAdapter);
        out.write(null);
        out.close();
        Toast.makeText(this, R.string.list_saved, Toast.LENGTH_SHORT).show();
        savedata(false);
        } catch (FileNotFoundException e){
            e.printStackTrace();
        } catch (IOException e){
            e.printStackTrace();
        }

    }
}

新!!:我编辑了 ScanBaseActivity 和 ScanBleActivity 以引入 xml 保存,但是当我运行应用程序时,当扫描停止时会导致错误(必须将列表保存在 sml 文件中的时刻)。有谁知道如何解决或纠正它??!!!

【问题讨论】:

标签: android xml list


【解决方案1】:

好的,首先,您需要重新调整处理适配器的方式,然后,一切都应该到位。

因此,我将外包给 vogella,它是优秀 android 设计模式的核心 http://www.vogella.com/tutorials/AndroidListView/article.html

你可以通读第 3 部分,吃点意大利面,然后回到这里,但你多读的每一行都是一件好事 =]

现在您有一个包含数据列表的活动,以及一个接收该列表的适配器 - 与您的代码相比有点愚蠢 - 将其应用于某种视图。当您想要更新该数据时,您可以通过在某处获取蓝牙设备列表的方法修改 activity 中的 List 对象 - 我会使用 AsyncTask 将该进程从线程中移除.

由于您将 List 传递给适配器,因此您可以等到在活动中填充数据,然后执行 adapter.notifyDataSetChanged。你不想adapter.add

那么你在活动中有一个很好的数据列表;如果它是正确的列表,您不必担心,因为——鉴于更新模式——它是唯一的列表!

然后按照 Merleverde 发布的链接将该数据序列化为 xml,可能在实用程序类中,但在您的活动中很好。

编辑: 这是一个非常好的适配器,这是显示动态变化数据的更大模式的一部分:

public class AnchorListAdapter extends ArrayAdapter<String>
{

private final List<String> anchorNames;
public AnchorListAdapter(Context context, int textviewId, List<String> anchors){
    super(context, textviewId, anchors);
    anchorNames = anchors;
}

@Override
public String getItem( int i ) {
    return anchorNames.get(i).toString();
}

}

【讨论】:

  • 这是我到目前为止所理解的,如果我弄错了,请纠正我。在我的课堂上,ScanBaseActivity 是我创建每个项目具有相同模式的列表的地方。我们在 ScanBleActivity 中进行扫描,并且 ScanBaseActivity 将使用找到的设备创建的列表传递给适配器。在适配器中,它根据找到的设备填充列表项的信息,并将更新的列表返回给 ScanBaseActivity。它一直持续到完成扫描周期,之后我的最终列表位于 ScanBaseActivity 中。我是对的?
  • almost =] ScanBleActivity[注意:这可能是 ScanBaseActivity 的服务类或 asyncTask 内部类] 返回一个列表给 ScanBaseActivity。 ScanBase 构造了一个带有空数据集的适配器,然后将适配器分配给一个列表视图。适配器基本上将列表与视图相关联,getCount 返回列表的大小,getView 返回 List.get(position)(到目前为止,我认为我们达成了一致)适配器绝对不返回任何内容;它在 getView/Item 期间使用字符串修改视图。
  • 查看适合我的典型适配器的编辑。 ScanBase Activity 无处可去(它为这些操作提供了整个上下文,并显示了列表所在的视图(例如 setContentView)(例如 ListView listView = ( ListView )findViewById( R.id.data_list_view ) );是,适配器中有一个列表,但它是ScanBaseActivity中的从属,要遵守的命令是adapter.notifyDataSetChanged()。
  • 因此,如果我需要保存最终列表,我应该做的是在 ScanBaseActivity 中的 addDevice 之后创建一个公共类,它保存列表并使用 Merlevede 提供的链接从中工作对吧??
  • =] 我会把那个静态方法放在一个 util 类中,是的。
【解决方案2】:

嗯,并不是您要从适配器中保存它,而是适配器要“调整”您将放入首选项的数据集。

作为一个领域:

private SharedPreferences saveHash;

在 onCreate 中:

saveHash = getSharedPreferences( getString( R.string.save_hash ), MODE_PRIVATE );

然后:

public void onFinishedLoading(){
    super.onPause();
    SharedPreferences.Editor editor = saveHash.edit();
    editor.clear();
    for( String s: myData){
        editor.putString(x, s);
    }
    editor.commit();
}

edit:意识到你想从一个列表中做一个哈希;你想要什么作为钥匙?

【讨论】:

  • 对不起,我不太明白。这是要创建一个xml文件吗?我应该把上面的代码放在哪里?
  • oh yes =] 它在内部 xml 文件中创建一个键/值哈希图 =] 现在,如果您想独立于 SharePreferences 访问该文件,请按照 Meleverde 的链接,但在正在加载该列表的异步任务结束
  • ...因为如果加载该列表需要花费任何时间,您可能已经将它从 UI 线程移到 asyncTask 上,并且有一个 onPostExecute 方法可以使用
  • 我明白了,但我仍然不知道应该在哪里实现此代码或如何导入项目列表。在我的应用程序中,我使用了一个 MainActivity 来检查蓝牙是否已启用以及它是否支持 ble。之后,它调用上面列出的类 ScanBleActivity。但是,我使用另一个名为 ScanBaseActivity 的类,它从 ListActivity 扩展而来,该类设置适配器并从 ScanBleActivity 启动扫描。我现在将其他课程放在一边,以便您了解更多
  • 我已经上传了丢失的课程。我应该在哪里修改它以及如何实现你说的代码?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-09
  • 1970-01-01
相关资源
最近更新 更多