仅在启动应用程序时显示启动画面,而不是每次调用包含启动画面代码的活动时都显示启动画面

时间:2016-04-06 13:22:29

标签: java android android-intent splash-screen

在我按问题描述之前,我想指出我知道其他线程提出这个问题,但是没有一个能够解决我的问题。

之前提出的问题和我的问题之间的区别在于我在主要活动中启动了屏幕代码,在另一个活动中启动了 NOT ,因此我没有布局XML文件。

所以,问题是,我只想在应用程序启动时显示启动画面,这是通过以下代码完美完成的,但是当main activity(包含启动画面代码)被另一个调用时使用Intent的活动,再次显示初始屏幕。

所以,首先我尝试使用flag变量,在创建活动时启动0,并在启动一次显示启动画面时将其递增1。但我发现它不会起作用,因为在创建活动时它总是0

所以,现在我正在尝试从其他活动传递一个字符串,并尝试再次阻止启动画面,如下面的代码所示:

public class Registration extends ActionBarActivity {

public final static String EXTRA_MESSAGE = "com.kaushal.myapplication.MESSAGE";

DatabaseHelper myDb;
EditText username,password;
private ImageView splashImageView;
boolean splashloading = false;
int flag=0;


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


    String message = null;
    Intent intent0 = getIntent();
    message = intent0.getStringExtra(Registration.EXTRA_MESSAGE);//string from another activity.

    if(!message.equals("signup has called me")) { //splash screen code in `if`
        splashImageView = new ImageView(this);
        //splashImageView.setBackgroundColor();
        splashImageView.setImageResource(R.drawable.sexy);
        setContentView(splashImageView);
        splashloading = false;
        Handler h = new Handler();

        h.postDelayed(new Runnable() {
            public void run() {
                splashloading = false;
                setContentView(R.layout.activity_registration);
                username = (EditText) findViewById(R.id.username);
                password = (EditText) findViewById(R.id.password);
            }
        }, 3000);
        flag++;
    }

    if(flag==0){
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
    }

    myDb = new DatabaseHelper(this);




}
}

此处Registration是我的主要活动的名称,该活动将在应用启动时启动。

另一个名为sign Up的活动的方法代码,它传递一个字符串:

 public void backToRegistration(View view){
    Intent intent0 = new Intent(this,Registration.class);
    intent0.putExtra(EXTRA_MESSAGE, "signup has called me");
    startActivity(intent0);
}

这种方法有什么问题?应用程序在启动后立即崩溃。

1 个答案:

答案 0 :(得分:1)

因此,在Intent中使用String作为这样的标志存在许多问题。字符串并没有真正为它设置。开销比简单的原始布尔标志更多。

以您目前正在尝试的方式执行此操作

将您的- (void)writeToKeychain { NSDictionary *attributes = NULL; NSMutableDictionary *updateItem = NULL; OSStatus result; if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr) { // First we need the attributes from the Keychain. updateItem = [NSMutableDictionary dictionaryWithDictionary:attributes]; // Second we need to add the appropriate search key/values. [updateItem setObject:[genericPasswordQuery objectForKey:(id)kSecClass] forKey:(id)kSecClass]; // Lastly, we need to set up the updated attribute list being careful to remove the class. NSMutableDictionary *tempCheck = [self dictionaryToSecItemFormat:self.keychainItemData]; [tempCheck removeObjectForKey:(id)kSecClass]; #if TARGET_IPHONE_SIMULATOR // Remove the access group if running on the iPhone simulator. // // Apps that are built for the simulator aren't signed, so there's no keychain access group // for the simulator to check. This means that all apps can see all keychain items when run // on the simulator. // // If a SecItem contains an access group attribute, SecItemAdd and SecItemUpdate on the // simulator will return -25243 (errSecNoAccessForItem). // // The access group attribute will be included in items returned by SecItemCopyMatching, // which is why we need to remove it before updating the item. [tempCheck removeObjectForKey:(id)kSecAttrAccessGroup]; #endif // An implicit assumption is that you can only update a single item at a time. result = SecItemUpdate((CFDictionaryRef)updateItem, (CFDictionaryRef)tempCheck); NSAssert( result == noErr, @"Couldn't update the Keychain Item." ); } else { // No previous item found; add the new one. result = SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:self.keychainItemData], NULL); NSAssert( result == noErr, @"Couldn't add the Keychain Item." ); } } 代码更改为此

onCreate

并添加此方法,我们将以一种递归的方式使用它来处理显示启动画面。

super.onCreate(savedInstanceState);

Intent intent0 = getIntent();
boolean showSplash = getIntent().getBooleanExtra(Registration.FLAG_KEY), true);

handleSplashScreen(showSplash);

然后,当您从另一个活动打开此活动时

private void handleSplashScreen(boolean showSplash){
    if(showSplash) { //splash screen code in `if`
        splashImageView = new ImageView(this);
        //splashImageView.setBackgroundColor();
        splashImageView.setImageResource(R.drawable.sexy);
        setContentView(splashImageView);
        splashloading = false;
        Handler h = new Handler();

        h.postDelayed(new Runnable() {
           public void run() {
               handleSplashScreen(false);
           }
        }, 3000);
    }
    else{
        splashloading = false;
        setContentView(R.layout.activity_registration);
        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
    }
}

其中public void backToRegistration(View view){ Intent intent0 = new Intent(this,Registration.class); intent0.putExtra(FLAG_KEY, false); startActivity(intent0); } FLAG_KEY并替换private static FLAG_KEY = com.kaushal.myapplication.FLAG;字符串。

我建议怎么做

现在,在说,这根本不是我建议如何做到这一点。您应该只有一个在启动时调用的SplashScreenActivity,并重定向到您的EXTRA_MESSAGE MainActivity。这样可以摆脱具有两种不同布局,标志等的活动的卷积。

Registration

R.layout.activity_splash看起来像这样

public class SplashScreenActivity extends Activity{

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);

        new Handler().postDelayed(new Runnable(){
            @Override
            public void run(){
                startActivity(new Intent(SplashScreenActivity.this, MainActivity.class);
                SplashScreenActivity.this.finish();
            }
        }, 3000);

    }
}

然后你可以像这样使用MainActivity

<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="R.drawable.sexy"
    android:scaleType="centerInside" />

最后,只需进入清单并进行更新,以便在启动时显示新创建的SplashScreenActivity,并确保仍然正确声明了MainActivity。

public class MainActivity extends ActionBarActivity{

    // Variables here
    ...

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_registration);

        username = (EditText) findViewById(R.id.username);
        password = (EditText) findViewById(R.id.password);
    }

    // Other methods
    ...
}

没有更多的旗帜,没有更多的逻辑,没有更多的问题。它会在启动时加载启动画面,就是这样。活动在传递意图后完成,因此它不再在堆栈上。一切都很好。其他问题处理这样的事情的原因是推荐使用启动画面的方式。