【问题标题】:Android - save/restore state of custom classAndroid - 保存/恢复自定义类的状态
【发布时间】:2014-05-28 06:30:39
【问题描述】:

我有一些 ssh 支持类 - 它在内部使用 jsch。我在主要活动中使用这个类,这样:

public class MainActivity extends Activity
{

 SshSupport ssh = new SshSupport();

.....

 @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);



    //Handle events for ssh
    ssh.eventHandler = new ISshEvents()
    {


        @Override
        public void SshCommandExecuted(SshCommandsEnum commandType, String result)
        {

        }

      //other overrides here


    }

        //Ssh operations on gui item click 
        @Override
        public void onItemClick(AdapterView<?> arg0, View v, int position, long arg3)
        {

            if (ssh.IsConnected() == false)
            {
                try
                {

                    ssh.ConnectAsync(/*parameters*/);

                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }

            try
            {
                ssh.ExecuteCommandAsync(SshCommandsEnum.values()[position]);
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }

        }
    });

}

效果很好。我的应用程序连接到 ssh,在后台线程中执行所有需要的操作,并将结果通过如上所示的事件报告给 gui。但是在用户更改设备方向后没有任何效果。对我来说很清楚 - 活动被重新创建并且所有状态都丢失了。不幸的是,我的 SshSupport 类对象也丢失了。

为动态更改/添加的对象存储 gui 状态非常容易(使用 put/get 可序列化等方法)。但我不知道如何防止我的 ssh 对象,ssh 连接会话丢失。

由于我的类不可序列化,我无法将其保存到捆绑包中。此外,即使我使我的 SshSupport 类可序列化,它使用的 jsch 对象仍然不可序列化。

那么解决这个问题的最佳方法是什么?此外,我需要执行一些后台操作(在我的 SshSupport 类中使用 AsyncTask)。并且应该向 MainActivity 报告进度。但同样,我的线程将在设备方向更改时被破坏。

[添加] 关于您的解决方案,我创建了保留片段并以这种方式处理它:

public class MainActivity extends Activity
{
    SshSupport ssh;
    private RetainedFragment dataFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
      super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        // find the retained fragment on activity restarts
        FragmentManager fm = getFragmentManager();
        dataFragment = (RetainedFragment) fm.findFragmentByTag("data");

        // create the fragment and data the first time
        if (dataFragment == null)
        {
            ssh = new SshSupport();

            // add the fragment
            dataFragment = new RetainedFragment();
            fm.beginTransaction().add(dataFragment, "data").commit();
            // load the data from the web
            dataFragment.setData(ssh);
        }

        ssh = dataFragment.getData();

        ssh.eventHandler = new ISshEvents()
        {

           .......

        }



   }

     @Override
    public void onDestroy()
     {
        super.onDestroy();
        // store the data in the fragment
        dataFragment.setData(ssh);
     }
}

这是正确的吗?它似乎可以正常工作。

【问题讨论】:

    标签: java android ssh bundle state


    【解决方案1】:

    那么解决这个问题的最佳方法是什么?

    使用保留的片段来管理您的 SSH 连接。我所说的“保留片段”是指您调用setRetainInstance(true) 的片段。该片段不会在配置更改时被销毁和重新创建。相反,它将被“保留”并直接交给新的活动实例,因此它所持有的任何东西都会被类似地保留。

    如果这个片段是一个没有 UI 的片段,通过 FragmentTransaction 添加是最安全的,尽管小心操作,您可以将此行为添加到现有的动态片段中。

    您可以在the online documentation 中阅读更多相关信息。

    【讨论】:

    • 所以如果我理解正确的文档示例。我应该将创建的 ssh 对象推送到上面示例中的 setData 吗?好的,但是如何处理我的事件?在将对象放入片段之前,我应该只分配一次事件吗?我的意思是事件覆盖
    • @user1209216:“我应该将创建的 ssh 对象推送到上面示例中的 setData 吗?” -- 您应该在片段的数据成员中保留您的“创建的 ssh 对象”。是否使用 getter 和 setter 取决于您。 “我应该只分配一次事件,然后再将我的对象碎片化吗?” ——大概。
    • @user1209216:从在配置更改中保持连接的角度来看,这应该可行。就个人而言,我只是将所有与 SSH 相关的逻辑移到片段中,以便更好地封装代码。
    猜你喜欢
    • 2017-01-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-23
    • 1970-01-01
    • 2013-04-04
    • 2014-04-25
    • 1970-01-01
    相关资源
    最近更新 更多