跳过 844 帧!简单的 AlertDialog with Spinners 导致 MainThread 中的工作过多
Skipped 844 frames! Too much work in MainThread caused by simple AlertDialog with Spinners
我使用带有两个微调器的 AlertDialog,应用程序本身非常快,但是当我启动这个对话框时应用程序变慢,当对话框完成时速度会上升。
其中一个Spinners真的很“重”,它包含60个元素,由一张图片和一个TextView组成。图片(ImageView)很小,但原图是512x512 PNG 12,54kB(这样大吗?)。
一个ArralyList(用于小微调器)直接初始化,小的在应用程序启动时初始化。
这是警报对话框
public class dialog_CardWithdrawRequest extends AppCompatDialogFragment {
private static final String TAG = "dialog_CardWithdrawRequ";
private ArrayList<obj_PrintState> printStatesList;
private Spinner sp_DialogCardWithdrawRequest_Printer;
private Spinner sp_DialogCardWithdrawRequest_Country;
private sendChoosenCountryAndPrintState listener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (dialog_CardWithdrawRequest.sendChoosenCountryAndPrintState) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() +
" must implement sendChoosenCountryAndPrintState listener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
initArrays();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme);
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_cardwithdrawrequest, null);
final int Driver;
final int iCurrentDriverPosition;
Bundle receivingBundle = this.getArguments();
if(receivingBundle != null){
Driver = receivingBundle.getInt("Driver");
iCurrentDriverPosition = receivingBundle.getInt("CurrentCountryPosition");
}else{
Driver = INT_DEFAULT_VALUE;
iCurrentDriverPosition =0;
}
builder.setView(view)
.setTitle(R.string.dialog_CardWithdrawRequest_Title);
builder.setNegativeButton(R.string.Cancle, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
obj_Country selectedCountry = (obj_Country) sp_DialogCardWithdrawRequest_Country.getSelectedItem();
String sSelectedCountry = selectedCountry.getsHexCountryCode();
obj_PrintState selectedPrintState = (obj_PrintState) sp_DialogCardWithdrawRequest_Printer.getSelectedItem();
String sSelectedPrintRequest = selectedPrintState.getsPrinterRequestHex();
listener.choosenCountryAndPrintState(sSelectedCountry, sSelectedPrintRequest, Driver);
}
});
sp_DialogCardWithdrawRequest_Country = view.findViewById(R.id.sp_DialogCardWithdrawRequest_Country);
sp_DialogCardWithdrawRequest_Printer = view.findViewById(R.id.sp_DialogCardWithdrawRequest_Printer);
adapter_Spinner_Country adapterCountry = new adapter_Spinner_Country(getContext(), objCountryList);
adapter_Spinner_Printer adapterPrinter = new adapter_Spinner_Printer(getContext(), printStatesList);
sp_DialogCardWithdrawRequest_Country.setAdapter(adapterCountry);
sp_DialogCardWithdrawRequest_Printer.setAdapter(adapterPrinter);
sp_DialogCardWithdrawRequest_Country.setSelection(iCurrentDriverPosition);
return builder.create();
}
private void initArrays(){
printStatesList = new ArrayList<>();
printStatesList.add(new obj_PrintState(PRINTREQUEST_NONE, getText(R.string.dialog_CardWithdrawRequest_PrintRequest_None).toString()));
printStatesList.add(new obj_PrintState(PRINTREQUEST_UTC, getText(R.string.dialog_CardWithdrawRequest_PrintRequest_UTC).toString()));
printStatesList.add(new obj_PrintState(PRINTREQUEST_LOCAL, getText(R.string.dialog_CardWithdrawRequest_PrintRequest_Local).toString()));
}
public interface sendChoosenCountryAndPrintState{
void choosenCountryAndPrintState(String sSelectedCountry, String sSelectedPrintRequest, int Driver);
}
}
这是来自mainActivity的调用
helperThread = new HandlerThread("HelperThread");
helperThread.start();
Handler helperHandler = new Handler(helperThread.getLooper());
helperHandler.post(new Runnable() {
@Override
public void run() {
dialog_CardWithdrawRequest dialog_cardWithdrawRequest = new dialog_CardWithdrawRequest();
Bundle information = new Bundle();
information.putInt("Driver", iDriver);
information.putInt("CurrentCountryPosition", finalIPosition);
dialog_cardWithdrawRequest.setArguments(information);
dialog_cardWithdrawRequest.show(getSupportFragmentManager(),"CardWithdrawRequest");
}
});
如您所见,我已经尝试 post 在不同的线程上进行这种“艰苦的工作”,但我认为 AlertDialog
总是在 UI 线程中运行,我不知道不知道。
我也试过用:
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
... 512x512 PNG 12,54kB (is this to large?)
... 是的,是的。
考虑到解压后的原始位图是 x * y * 4 字节(R、G、B 和 A 分量,每个分量占 1 个完整字节)。
因此,您的每个图像在内存中占 1 MB。
顺便说一下,不需要使用 ImageView:只需将图像设置为 TextView 中的复合可绘制对象并挤出一些性能。
这是一个有趣的 link:
https://antonioleiva.com/textview_power_drawables/
我使用带有两个微调器的 AlertDialog,应用程序本身非常快,但是当我启动这个对话框时应用程序变慢,当对话框完成时速度会上升。
其中一个Spinners真的很“重”,它包含60个元素,由一张图片和一个TextView组成。图片(ImageView)很小,但原图是512x512 PNG 12,54kB(这样大吗?)。
一个ArralyList(用于小微调器)直接初始化,小的在应用程序启动时初始化。
这是警报对话框
public class dialog_CardWithdrawRequest extends AppCompatDialogFragment {
private static final String TAG = "dialog_CardWithdrawRequ";
private ArrayList<obj_PrintState> printStatesList;
private Spinner sp_DialogCardWithdrawRequest_Printer;
private Spinner sp_DialogCardWithdrawRequest_Country;
private sendChoosenCountryAndPrintState listener;
@Override
public void onAttach(Context context) {
super.onAttach(context);
try {
listener = (dialog_CardWithdrawRequest.sendChoosenCountryAndPrintState) context;
} catch (ClassCastException e) {
throw new ClassCastException(context.toString() +
" must implement sendChoosenCountryAndPrintState listener");
}
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
initArrays();
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme);
LayoutInflater inflater = getActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.dialog_cardwithdrawrequest, null);
final int Driver;
final int iCurrentDriverPosition;
Bundle receivingBundle = this.getArguments();
if(receivingBundle != null){
Driver = receivingBundle.getInt("Driver");
iCurrentDriverPosition = receivingBundle.getInt("CurrentCountryPosition");
}else{
Driver = INT_DEFAULT_VALUE;
iCurrentDriverPosition =0;
}
builder.setView(view)
.setTitle(R.string.dialog_CardWithdrawRequest_Title);
builder.setNegativeButton(R.string.Cancle, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
});
builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
obj_Country selectedCountry = (obj_Country) sp_DialogCardWithdrawRequest_Country.getSelectedItem();
String sSelectedCountry = selectedCountry.getsHexCountryCode();
obj_PrintState selectedPrintState = (obj_PrintState) sp_DialogCardWithdrawRequest_Printer.getSelectedItem();
String sSelectedPrintRequest = selectedPrintState.getsPrinterRequestHex();
listener.choosenCountryAndPrintState(sSelectedCountry, sSelectedPrintRequest, Driver);
}
});
sp_DialogCardWithdrawRequest_Country = view.findViewById(R.id.sp_DialogCardWithdrawRequest_Country);
sp_DialogCardWithdrawRequest_Printer = view.findViewById(R.id.sp_DialogCardWithdrawRequest_Printer);
adapter_Spinner_Country adapterCountry = new adapter_Spinner_Country(getContext(), objCountryList);
adapter_Spinner_Printer adapterPrinter = new adapter_Spinner_Printer(getContext(), printStatesList);
sp_DialogCardWithdrawRequest_Country.setAdapter(adapterCountry);
sp_DialogCardWithdrawRequest_Printer.setAdapter(adapterPrinter);
sp_DialogCardWithdrawRequest_Country.setSelection(iCurrentDriverPosition);
return builder.create();
}
private void initArrays(){
printStatesList = new ArrayList<>();
printStatesList.add(new obj_PrintState(PRINTREQUEST_NONE, getText(R.string.dialog_CardWithdrawRequest_PrintRequest_None).toString()));
printStatesList.add(new obj_PrintState(PRINTREQUEST_UTC, getText(R.string.dialog_CardWithdrawRequest_PrintRequest_UTC).toString()));
printStatesList.add(new obj_PrintState(PRINTREQUEST_LOCAL, getText(R.string.dialog_CardWithdrawRequest_PrintRequest_Local).toString()));
}
public interface sendChoosenCountryAndPrintState{
void choosenCountryAndPrintState(String sSelectedCountry, String sSelectedPrintRequest, int Driver);
}
}
这是来自mainActivity的调用
helperThread = new HandlerThread("HelperThread");
helperThread.start();
Handler helperHandler = new Handler(helperThread.getLooper());
helperHandler.post(new Runnable() {
@Override
public void run() {
dialog_CardWithdrawRequest dialog_cardWithdrawRequest = new dialog_CardWithdrawRequest();
Bundle information = new Bundle();
information.putInt("Driver", iDriver);
information.putInt("CurrentCountryPosition", finalIPosition);
dialog_cardWithdrawRequest.setArguments(information);
dialog_cardWithdrawRequest.show(getSupportFragmentManager(),"CardWithdrawRequest");
}
});
如您所见,我已经尝试 post 在不同的线程上进行这种“艰苦的工作”,但我认为 AlertDialog
总是在 UI 线程中运行,我不知道不知道。
我也试过用:
runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
... 512x512 PNG 12,54kB (is this to large?)
... 是的,是的。
考虑到解压后的原始位图是 x * y * 4 字节(R、G、B 和 A 分量,每个分量占 1 个完整字节)。
因此,您的每个图像在内存中占 1 MB。
顺便说一下,不需要使用 ImageView:只需将图像设置为 TextView 中的复合可绘制对象并挤出一些性能。
这是一个有趣的 link:
https://antonioleiva.com/textview_power_drawables/