Android中向上和返回按钮的区别

7
我正在尝试创建一个基本的“找到最近的...”应用程序,作为学习练习。
我有3个活动:
1. 主要活动,用户在其中输入自己的地址,通过意图将对象数组传递给列表活动。 2. 列表活动,显示最近的10个地点。当选择一个项目时,它通过意图将对象传递给详细信息活动。 3. 详细信息活动,显示所选位置的详细信息。
我已经完成了大部分工作,但是我注意到了一个小问题,即返回按钮(在我的手机屏幕底部)和上按钮(在操作栏上)之间的差异。经过研究,两者在这种情况下似乎应该表现相同。当点击返回按钮时,一切都按预期工作,并且我们仍然看到相同的列表。然而,当点击上按钮时,它似乎以不同的方式启动/恢复列表活动,并且列表中的数据已经消失了。
是否有人能够解释一下为什么会发生这种情况以及如何防止它发生?
以下是我的代码:(欢迎对我的Android / Java技术提出任何批评!)
MainActivity.java
public class MainActivity extends Activity {

    public final static String TRACKS = "com.example.firstapp.TRACKS";

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

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    /** Called when the user clicks the 'Search' button */
    public void search(View view) {

        // Get Address Text
        // EditText editText = (EditText) findViewById(R.id.edit_address);
        // String address = editText.getText().toString();

        // Get tracks near to address
        Track[] trackArray = new Track[20];

        for(int i=0; i < trackArray.length; i++) {
            trackArray[i] = new Track("Track " + i, "Address" + i, (float) Math.random()*10);
        }

        // Fire intent to show results
        Intent intent = new Intent(this, TrackListActivity.class);
        intent.putExtra(TRACKS, trackArray);
        startActivity(intent);
    }

}

TrackListActivity.java

public class TrackListActivity extends ListActivity {

    public final static String TRACK = "com.mycroft.runtrackdir.TRACK";

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();

        if (intent.hasExtra(MainActivity.TRACKS)) {
            Parcelable[] tempTrackArray = intent.getParcelableArrayExtra(MainActivity.TRACKS);        

            // Cast Parcelable to Track
            Track[] trackArray = new Track[tempTrackArray.length];
            for(int i=0; i < trackArray.length; i++) {
                trackArray[i] = (Track) tempTrackArray[i];
            }

            ArrayAdapter<Track> arrayAdapter = new ArrayAdapter<Track>(this, android.R.layout.simple_list_item_1, trackArray);
            setListAdapter(arrayAdapter);
        }
    }

    @Override
    protected void onListItemClick (ListView l, View v, int position, long id) {
        Track clickedTrack = (Track) l.getItemAtPosition(position);

        // Fire intent to show detail
        Intent intent = new Intent(this, TrackDetailActivity.class);
        intent.putExtra(TRACK, clickedTrack);
        startActivity(intent);
    }
}

TrackDetailActivity.java

public class TrackDetailActivity extends Activity {

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

        Intent intent = getIntent();
        Track track = intent.getParcelableExtra(TrackListActivity.TRACK);

        setContentView(R.layout.activity_track_detail);

        TextView track_name = (TextView) findViewById(R.id.track_name);
        TextView track_address = (TextView) findViewById(R.id.track_address);
        TextView track_distance = (TextView) findViewById(R.id.track_distance);

        track_name.setText(track.name);
        track_address.setText(track.address);
        track_distance.setText(track.distance.toString());

    }
}

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.firstapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.firstapp.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.example.firstapp.TrackListActivity"
            android:label="@string/title_activity_track_list"
            android:parentActivityName="com.example.firstapp.MainActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.example.firstapp.MainActivity" />
        </activity>
        <activity
            android:name="com.example.firstapp.TrackDetailActivity"
            android:label="@string/title_activity_track_detail"
            android:parentActivityName="com.example.firstapp.TrackListActivity" >
            <meta-data
                android:name="android.support.PARENT_ACTIVITY"
                android:value="com.example.firstapp.TrackListActivity" />
        </activity>
    </application>

</manifest>
3个回答

4
我认为你需要修改你的 Manifest.xml 文件并告知你的 Manifest 文件 中各个活动之间的关系。这可以解决问题。
例如:
<application ... >
...
<!-- The main/home activity (has no parent activity) -->
<activity
    android:name="com.example.myfirstapp.MainActivity" ...>
    ...
</activity>
<!-- A child of the main activity -->
<activity
    android:name="com.example.myfirstapp.DisplayMessageActivity"
    android:label="@string/title_activity_display_message"
    android:parentActivityName="com.example.myfirstapp.MainActivity" >
    <!-- Parent activity meta-data to support API level 7+ -->
    <meta-data
        android:name="android.support.PARENT_ACTIVITY"
        android:value="com.example.myfirstapp.MainActivity" />
</activity>

您还可以查看此文档

编辑:
如果在某些活动中收到空意图,您还可以使用数据持久性。 对于Android中的数据持久性,您可以使用共享首选项SQLite数据库序列化等。

由于您正在学习Android开发,因此在从主活动启动列表活动并在onResume中从共享首选项中加载trackArray的数据,并在onCreate中填充它时,您可以将trackArray值简单地放入应用程序的共享首选项中。 这样,您的操作栏的向上按钮将不会使ListView活动的数据消失。

P.S:共享首选项的实际目的是存储大小较小且偶尔更改的值,例如特定应用程序的设置数据。因此,请不要滥用它。


这个列表活动的父级是主活动。详细活动的父级是列表活动。这应该是正确的吧?我会将我的清单文件添加到原始帖子中。 - WMycroft
1
我认为当动作栏中的返回按钮被按下时,你的列表活动的onCreate或onResume函数被调用了,因此列表活动收到了一个空的意图而没有填充数据。 - Salman Khakwani
1
您可以通过放置日志并检查当按下操作栏的返回按钮时,List Activity 中是否调用了 onCreateonResume 来验证我的诊断。 - Salman Khakwani
嗨@salman,感谢您的帮助。您是正确的,当按下返回按钮时,只会调用onResume,但是当按下向上按钮时,会调用onCreateonResume,导致了我的当前情况。您编辑后的答案似乎含糊不清,首先建议使用Shared Pref's,然后提到这是不好的做法。难道没有更好的解决方案吗?我发现改变主页按钮的默认行为可以解决我的问题,通过在详细活动中按下主页时调用finish。这是不好的做法还是可行的解决方案? - WMycroft
1
@user2665900 我要求你暂时使用Shared Prefs,因为它会让你体验到在Android开发中进行数据持久化的味道。更改Home按钮的默认行为并在单击时结束当前活动并不是一种不好的做法。但是,从长远来看,我建议您选择数据持久性(SQLite数据库)来管理用户的查询。这将帮助您摆脱在活动切换期间数据丢失的担忧,并通过包括用户搜索历史记录和其他相关数据来进一步增强应用程序的功能。 - Salman Khakwani

1
  • 向上按钮和返回按钮的区别。

返回按钮- 返回按钮将您带回到您之前活动的最后一个位置。

向上按钮- 向上按钮以分层或祖先方式向上一级。无论您上次活动的是哪个,您始终会被重定向到您在清单中设置的父级活动。

尽管在许多情况下返回和向上按钮几乎执行相同的操作,但它们在幕后执行完全不同的步骤。


0
将“launchMode =“ singleTop””添加到您的清单文件中的TrackListActivity。
<activity
        android:name="com.example.firstapp.TrackListActivity"
        android:label="@string/title_activity_track_list"
        android:launchMode="singleTop"
        android:parentActivityName="com.example.firstapp.MainActivity" >
        <meta-data
            android:name="android.support.PARENT_ACTIVITY"
            android:value="com.example.firstapp.MainActivity" />
</activity>

如果你不想在按上一步按钮时重新启动并杀死你的活动,那么你需要使用launchMode="singleTop"。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接