有没有一种方法可以从不继承Activity类的类中调用`overridePendingTransition`?

11

我正在使用另一个类在主活动显示时运行一些后台任务,并将该活动的上下文传递给此后台类。我从这个后台类启动了另一个活动,但无法调用overridePendingTransition,因为“方法overridePendingTransition(int,int)未定义为BackgroundClass类型。”

public class GetUPC extends AsyncTask<Void, Void, Void> 
{       
    @Override
    protected void onPreExecute() 
    {
        ...
    }
    @Override
    protected Void doInBackground(Void... arg0) 
    {
        ...


                    boolean dairy;
                    if(theDairy.equals("N"))
                    {
                        //milk test
                        dairy=true;
                    }
                    else
                    {
                        dairy=false;
                    }



                    //depending on if there is a warning it will either display the warning screen or skip it
                    if(dairy)
                    {
                        Intent intent_warn = new Intent(context, WarningScreen.class);

                        intent_warn.putExtra("Name", str_name);
                        intent_warn.putExtra("Size", str_size);
                        intent_warn.putExtra("Price", str_price);
                        intent_warn.putExtra("Carbs", str_carbs);
                        intent_warn.putExtra("Protein", str_protein);
                        intent_warn.putExtra("Fiber", str_fiber);
                        intent_warn.putExtra("Sugar", str_sugar);
                        intent_warn.putExtra("SatFat", str_satFat);
                        intent_warn.putExtra("TotFat", str_totFat);
                        intent_warn.putExtra("Cholesterol", str_cholesterol);
                        intent_warn.putExtra("Sodium", str_sodium);
                        intent_warn.putExtra("Potassium", str_potassium);
                        intent_warn.putExtra("Calories", str_calories);
                        intent_warn.putExtra("Warning", "Contains Dairy");
                        intent_warn.putExtra("WarningRed", true);
                        Log.e("Warning",intent_warn.getExtras().getString("Warning"));

                        context.startActivity(intent_warn);
                        overridePendingTransition(R.layout.fade_in, R.layout.fade_out);  //THIS PART ISN'T WORKING//
                    }
                    else
                    {
                        Intent intent_menu = new Intent(context, DisplayScreen.class);
                        intent_menu.putExtra("Name", str_name);
                        intent_menu.putExtra("Size", str_size);
                        intent_menu.putExtra("Price", str_price);
                        intent_menu.putExtra("Carbs", str_carbs);
                        intent_menu.putExtra("Protein", str_protein);
                        intent_menu.putExtra("Fiber", str_fiber);
                        intent_menu.putExtra("Sugar", str_sugar);
                        intent_menu.putExtra("SatFat", str_satFat);
                        intent_menu.putExtra("TotFat", str_totFat);
                        intent_menu.putExtra("Cholesterol", str_cholesterol);
                        intent_menu.putExtra("Sodium", str_sodium);
                        intent_menu.putExtra("Potassium", str_potassium);
                        intent_menu.putExtra("Calories", str_calories);
                        intent_menu.putExtra("Warning",  "Contains no allergens");
                        intent_menu.putExtra("WarningRed", false);
                        Log.e("Warning",intent_menu.getExtras().getString("Warning"));

                        context.startActivity(intent_menu);
                    }


                    Log.e("KYLE_DATA_UPCH",str_name+" "+str_price+""+str_size);
                } 
            }
                catch (JSONException e) 
                {
                    e.printStackTrace();
                }

            } 
            else 
            {
                Log.e("ServiceHandler", "Couldn't get any data from the url");
                _errorCode=3;
            }

            return null;
        }
    @Override
    protected void onPostExecute(Void result) 
    {
        ...
    }



}
5个回答

33

所以我最终通过对上下文进行类型转换为Activity,并调用overridePendingTransition方法来解决了这个问题。

((Activity) context).overridePendingTransition(R.layout.fade_in, R.layout.fade_out);

我意识到这不是最佳实践,而且在更复杂的应用程序中可能会变得混乱,但就目前而言,我认为这是可以接受的。我最终希望调查@bariscan Kayaoglu的解决方案,因为它似乎更加强大。


1
请注意,如果上下文不是Activity,这将导致崩溃。首先检查上下文是否为Activity。 - IIRed-DeathII

9

为了加强Tims答案的安全性,请在进行类型转换之前检查上下文是否是Activity的实例:

if (context instanceof Activity) {
  ((Activity) context).overridePendingTransition(R.layout.fade_in, R.layout.fade_out);
}

这只是确保你调用的方法真正存在。你也可以使用try/catch,但我认为这已经足够了。


2
为什么我们不能只使用context.overridePendingTransition,因为context是Activity的一个实例?@Bjorn - blackHawk

2
最好创建一个接口并回调其方法。
myInterface mInterface;
public interface myInterface {
    public abstract void myTask();
}

public GetUPC(myInterface mInterface) {
    this.mInterface = mInterface;
}

在您的doInBackground方法中,当您完成时,请调用

mInterface.myTask();

不要忘记将你的接口实现到你的活动中,并在创建异步任务时将其发送到构造函数中。
myAsyncTask = new GetUPC(this);

您的开发平台将提示您实现未实现的方法,例如myTask()。在该方法中,您可以自由操作并访问您的活动。


这里myTask()具体会做什么?接口是否作为另一个活动?那我需要将意图传递给接口吗? - Tim
你可以在myTask()中调用overridePendingTransition(R.layout.fade_in, R.layout.fade_out);,因为它是一个抽象方法,你将在你的activity中填写它,而this将是你的activity。但正如我之前所说,你要么将你的上下文转换为activity,要么使用接口来触发异步任务结束时的时间,结果将是相同的,你可能会在Activity为空时触发你的myTask()方法或(Activity)context。正如我之前所说的,异步任务是一个后台线程,它无法知道你正在哪个activity上。 - Barışcan Kayaoğlu
更安全的方法是设置一个静态的Activity对象,并在每次打开新意图时设置它。假设我们创建了一个名为Statics的类,并声明了一个静态的Activity,public static Activity activity; 每次创建新意图时,在onCreate中将其设置为 Statics.activity = this; 这样可以确保您的活动对象不会为空。但是,如果您有内存问题,持有静态活动很可能会导致内存泄漏。 - Barışcan Kayaoğlu

0

我认为那不是一个好主意。因为你的类是一个异步任务,你选择的活动可能不是活动状态,因为你的异步任务将在后台工作。但如果你考虑到内存泄漏和空指针,你可以把你的活动发送到你的构造函数中。


当你说我会选择的活动时,你是指我将从这个异步任务开始的活动吗?因为不管怎样,除非返回错误,否则将启动两个活动中的任何一个。那么,为什么这样做会是一个坏主意呢? - Tim
假设您在屏幕上启动了一个意图Activity1。从Activity1启动异步任务并将Activity1发送到异步任务构造函数。然后,在异步任务在Activity1对象后台工作时,启动另一个意图Activity2。如果您在异步任务中使用Activity1对象,则会根据内存或所做更改而获得空指针异常,因为您的活动是Activity2。这就是异步任务的全部意义,它可以异步工作。 - Barışcan Kayaoğlu

0

在后台线程中无法进行任何UI更新部分,但如果想要这样做,则可以重写AsyncTask类的onProgressUpdate方法,并将您的活动启动代码粘贴在其中。要调用此方法,请调用publishProgress。在启动活动之前,您必须取消AsyncTask,否则您的应用程序将崩溃。


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